[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (monty:2726)
#At lp:maria/5.2 based on revid:monty@askmonty.org-20091014125853-gix3sqkenbazrrqz 2726 Michael Widenius 2009-10-19 This is based on the userstatv2 patch from Percona and OurDelta. The original code comes, as far as I know, from Google (Mark Callaghan's team) with additional work from Percona, Ourdelta and Weldon Whipple. This code provides the same functionallity, but with a lot of changes to make it faster and better fit the MariaDB infrastucture. Added new status variables: - Com_show_client_statistics, Com_show_index_statistics, Com_show_table_statistics, Com_show_user_statistics - Access_denied_errors, Busy_time (clock time), Binlog_bytes_written, Cpu_time, Empty_queries, Rows_sent, Rows_read Added new variable / startup option 'userstat' to control if user statistics should be enabled or not Added my_getcputime(); Returns cpu time used by this thread. New FLUSH commands: - FLUSH SLOW QUERY LOG - FLUSH TABLE_STATISTICS - FLUSH INDEX_STATISTICS - FLUSH USER_STATISTICS - FLUSH CLIENT_STATISTICS New SHOW commands: - SHOW CLIENT_STATISTICS - SHOW USER_STATISTICS - SHOW TABLE_STATISTICS - SHOW INDEX_STATISTICS New Information schemas: - CLIENT_STATISTICS - USER_STATISTICS - INDEX_STATISTICS - TABLE_STATISTICS Added support for all new flush commands to mysqladmin Added handler::ha_... wrappers for all handler read calls to do statistics counting - Changed all code to use new ha_... calls - Count number of read rows, changed rows and rows read trough an index Added counting of number of bytes sent to binary log (status variable Binlog_bytes_written) Added counting of access denied errors (status variable Access_denied_erors) Bugs fixed: - Fixed bug in add_to_status() and add_diff_to_status() where longlong variables where threated as long - CLOCK_GETTIME was not propely working on Linuxm added: mysql-test/r/status_user.result mysql-test/t/status_user-master.opt mysql-test/t/status_user.test modified: client/mysqladmin.cc configure.in include/my_sys.h include/mysql_com.h mysql-test/r/information_schema.result mysql-test/r/information_schema_all_engines.result mysql-test/r/information_schema_db.result mysql-test/r/log_slow.result mysql-test/t/log_slow.test mysys/my_getsystime.c sql/authors.h sql/event_data_objects.cc sql/event_db_repository.cc sql/filesort.cc sql/ha_partition.cc sql/handler.cc sql/handler.h sql/item_subselect.cc sql/lex.h sql/log.cc sql/log.h sql/log_event.cc sql/log_event_old.cc sql/mysql_priv.h sql/mysqld.cc sql/opt_range.cc sql/opt_range.h sql/opt_sum.cc sql/records.cc sql/set_var.cc sql/sp.cc sql/sql_acl.cc sql/sql_base.cc sql/sql_class.cc sql/sql_class.h sql/sql_connect.cc sql/sql_cursor.cc sql/sql_handler.cc sql/sql_help.cc sql/sql_insert.cc sql/sql_lex.h sql/sql_parse.cc sql/sql_plugin.cc sql/sql_prepare.cc sql/sql_select.cc sql/sql_servers.cc sql/sql_show.cc sql/sql_table.cc sql/sql_udf.cc sql/sql_update.cc sql/sql_yacc.yy sql/structs.h sql/table.cc sql/table.h sql/tztime.cc per-file messages: client/mysqladmin.cc Added support for all new flush commmands and some common combinations: flush-slow-log flush-table-statistics flush-index-statistics flush-user-statistics flush-client-statistics flush-all-status flush-all-statistics configure.in Added checking if clock_gettime needs the librt. (Fixes Bug #37639 clock_gettime is never used/enabled in Linux/Unix) include/my_sys.h Added my_getcputime() include/mysql_com.h Added LIST_PROCESS_HOST_LEN & new REFRESH target defines mysql-test/r/information_schema.result New information schema tables added mysql-test/r/information_schema_all_engines.result New information schema tables added mysql-test/r/information_schema_db.result New information schema tables added mysql-test/r/log_slow.result Added testing that flosh slow query logs is accepted mysql-test/r/status_user.result Basic testing of user, client, table and index statistics mysql-test/t/log_slow.test Added testing that flosh slow query logs is accepted mysql-test/t/status_user-master.opt Ensure that we get a fresh restart before running status_user.test mysql-test/t/status_user.test Basic testing of user, client, table and index statistics mysys/my_getsystime.c Added my_getcputime() Returns cpu time used by this thread. sql/authors.h Updated authors to have core and original MySQL developers first. sql/event_data_objects.cc Updated call to mysql_reset_thd_for_next_command() sql/event_db_repository.cc Changed to use new ha_... calls sql/filesort.cc Changed to use new ha_... calls sql/ha_partition.cc Changed to use new ha_... calls Fixed comment syntax sql/handler.cc Changed to use new ha_... calls Reset table statistics Added code to update global table and index status Added counting of rows changed sql/handler.h Added table and index statistics variables Added function reset_statistics() Added handler::ha_... wrappers for all handler read calls to do statistics counting Protected all normal read calls to ensure we use the new calls in the server. Made ha_partition a friend class so that partition code can call the old read functions sql/item_subselect.cc Changed to use new ha_... calls sql/lex.h Added keywords for new information schema tables and flush commands sql/log.cc Added flush_slow_log() Added counting of number of bytes sent to binary log Removed not needed test of thd (It's used before, so it's safe to use) Added THD object to MYSQL_BIN_LOG::write_cache() to simplify statistics counting sql/log.h Added new parameter to write_cache() Added flush_slow_log() functions. sql/log_event.cc Updated call to mysql_reset_thd_for_next_command() Changed to use new ha_... calls sql/log_event_old.cc Updated call to mysql_reset_thd_for_next_command() Changed to use new ha_... calls sql/mysql_priv.h Updated call to mysql_reset_thd_for_next_command() Added new statistics functions and variables needed by these. sql/mysqld.cc Added new statistics variables and structures to handle these Added new status variables: - Com_show_client_statistics, Com_show_index_statistics, Com_show_table_statistics, Com_show_user_statistics - Access_denied_errors, Busy_time (clock time), Binlog_bytes_written, Cpu_time, Empty_queries, Rows_set, Rows_read Added new option 'userstat' to control if user statistics should be enabled or not sql/opt_range.cc Changed to use new ha_... calls sql/opt_range.h Changed to use new ha_... calls sql/opt_sum.cc Changed to use new ha_... calls sql/records.cc Changed to use new ha_... calls sql/set_var.cc Added variable 'userstat' sql/sp.cc Changed to use new ha_... calls sql/sql_acl.cc Changed to use new ha_... calls Added counting of access_denied_errors sql/sql_base.cc Added call to statistics functions sql/sql_class.cc Added usage of org_status_var, to store status variables at start of command Added functions THD::update_stats(), THD::update_all_stats() Fixed bug in add_to_status() and add_diff_to_status() where longlong variables where threated as long sql/sql_class.h Added new status variables to status_var Moved variables that was not ulong in status_var last. Added variables to THD for storing temporary values during statistics counting sql/sql_connect.cc Variables and functions to calculate user and client statistics Added counting of access_denied_errors and lost_connections sql/sql_cursor.cc Changed to use new ha_... calls sql/sql_handler.cc Changed to use new ha_... calls sql/sql_help.cc Changed to use new ha_... calls sql/sql_insert.cc Changed to use new ha_... calls sql/sql_lex.h Added SQLCOM_SHOW_USER_STATS, SQLCOM_SHOW_TABLE_STATS, SQLCOM_SHOW_INDEX_STATS, SQLCOM_SHOW_CLIENT_STATS sql/sql_parse.cc Added handling of: - SHOW CLIENT_STATISTICS - SHOW USER_STATISTICS - SHOW TABLE_STATISTICS - SHOW INDEX_STATISTICS Added handling of new FLUSH commands: - FLUSH SLOW QUERY LOGS - FLUSH TABLE_STATISTICS - FLUSH INDEX_STATISTICS - FLUSH USER_STATISTICS - FLUSH CLIENT_STATISTICS Added THD parameter to mysql_reset_thd_for_next_command() Added initialization and calls to user statistics functions Added increment of statistics variables empty_queries, rows_sent and access_denied_errors. Added counting of cpu time per query sql/sql_plugin.cc Changed to use new ha_... calls sql/sql_prepare.cc Updated call to mysql_reset_thd_for_next_command() sql/sql_select.cc Changed to use new ha_... calls Indentation changes sql/sql_servers.cc Changed to use new ha_... calls sql/sql_show.cc Added counting of access denied errors Added function for new information schema tables: - CLIENT_STATISTICS - USER_STATISTICS - INDEX_STATISTICS - TABLE_STATISTICS Changed to use new ha_... calls sql/sql_table.cc Changed to use new ha_... calls sql/sql_udf.cc Changed to use new ha_... calls sql/sql_update.cc Changed to use new ha_... calls sql/sql_yacc.yy Add new show and flush commands sql/structs.h Add name_length to KEY to avoid some strlen Added cache_name to KEY for fast storage of keyvalue in cache Added structs USER_STATS, TABLE_STATS, INDEX_STATS Added function prototypes for statistics functions sql/table.cc Store db+table+index name into keyinfo->cache_name sql/table.h Added new information schema tables sql/tztime.cc Changed to use new ha_... calls === modified file 'client/mysqladmin.cc' --- a/client/mysqladmin.cc 2009-09-07 20:50:10 +0000 +++ b/client/mysqladmin.cc 2009-10-19 17:14:48 +0000 @@ -23,7 +23,7 @@ #include <sys/stat.h> #include <mysql.h> -#define ADMIN_VERSION "8.42" +#define ADMIN_VERSION "9.0" #define MAX_MYSQL_VAR 512 #define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */ #define MAX_TRUNC_LENGTH 3 @@ -96,7 +96,10 @@ enum commands { ADMIN_FLUSH_HOSTS, ADMIN_FLUSH_TABLES, ADMIN_PASSWORD, ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS, ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE, - ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD + ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD, ADMIN_FLUSH_SLOW_LOG, + ADMIN_FLUSH_TABLE_STATISTICS, ADMIN_FLUSH_INDEX_STATISTICS, + ADMIN_FLUSH_USER_STATISTICS, ADMIN_FLUSH_CLIENT_STATISTICS, + ADMIN_FLUSH_ALL_STATUS, ADMIN_FLUSH_ALL_STATISTICS }; static const char *command_names[]= { "create", "drop", "shutdown", @@ -106,7 +109,10 @@ static const char *command_names[]= { "flush-hosts", "flush-tables", "password", "ping", "extended-status", "flush-status", "flush-privileges", "start-slave", "stop-slave", - "flush-threads","old-password", + "flush-threads", "old-password", "flush-slow-log", + "flush-table-statistics", "flush-index-statistics", + "flush-user-statistics", "flush-client-statistics", + "flush-all-status", "flush-all-statistics", NullS }; @@ -518,7 +524,8 @@ static int execute_commands(MYSQL *mysql for (; argc > 0 ; argv++,argc--) { - switch (find_type(argv[0],&command_typelib,2)) { + int command; + switch ((command= find_type(argv[0],&command_typelib,2))) { case ADMIN_CREATE: { char buff[FN_REFLEN+20]; @@ -596,7 +603,11 @@ static int execute_commands(MYSQL *mysql if (mysql_refresh(mysql, (uint) ~(REFRESH_GRANT | REFRESH_STATUS | REFRESH_READ_LOCK | REFRESH_SLAVE | - REFRESH_MASTER))) + REFRESH_MASTER | REFRESH_TABLE_STATS | + REFRESH_INDEX_STATS | + REFRESH_USER_STATS | + REFRESH_SLOW_QUERY_LOG | + REFRESH_CLIENT_STATS))) { my_printf_error(0, "refresh failed; error: '%s'", error_flags, mysql_error(mysql)); @@ -614,7 +625,8 @@ static int execute_commands(MYSQL *mysql case ADMIN_VER: new_line=1; print_version(); - puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc."); + puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc,\n" + "2009 Monty Program Ab"); puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"); printf("Server version\t\t%s\n", mysql_get_server_info(mysql)); printf("Protocol version\t%d\n", mysql_get_proto_info(mysql)); @@ -790,9 +802,19 @@ static int execute_commands(MYSQL *mysql } case ADMIN_FLUSH_LOGS: { - if (mysql_refresh(mysql,REFRESH_LOG)) + if (mysql_query(mysql,"flush logs")) { - my_printf_error(0, "refresh failed; error: '%s'", error_flags, + my_printf_error(0, "flush failed; error: '%s'", error_flags, + mysql_error(mysql)); + return -1; + } + break; + } + case ADMIN_FLUSH_SLOW_LOG: + { + if (mysql_query(mysql,"flush slow query logs")) + { + my_printf_error(0, "flush failed; error: '%s'", error_flags, mysql_error(mysql)); return -1; } @@ -802,7 +824,7 @@ static int execute_commands(MYSQL *mysql { if (mysql_query(mysql,"flush hosts")) { - my_printf_error(0, "refresh failed; error: '%s'", error_flags, + my_printf_error(0, "flush failed; error: '%s'", error_flags, mysql_error(mysql)); return -1; } @@ -812,7 +834,7 @@ static int execute_commands(MYSQL *mysql { if (mysql_query(mysql,"flush tables")) { - my_printf_error(0, "refresh failed; error: '%s'", error_flags, + my_printf_error(0, "flush failed; error: '%s'", error_flags, mysql_error(mysql)); return -1; } @@ -822,7 +844,71 @@ static int execute_commands(MYSQL *mysql { if (mysql_query(mysql,"flush status")) { - my_printf_error(0, "refresh failed; error: '%s'", error_flags, + my_printf_error(0, "flush failed; error: '%s'", error_flags, + mysql_error(mysql)); + return -1; + } + break; + } + case ADMIN_FLUSH_TABLE_STATISTICS: + { + if (mysql_query(mysql,"flush table_statistics")) + { + my_printf_error(0, "flush failed; error: '%s'", error_flags, + mysql_error(mysql)); + return -1; + } + break; + } + case ADMIN_FLUSH_INDEX_STATISTICS: + { + if (mysql_query(mysql,"flush index_statistics")) + { + my_printf_error(0, "flush failed; error: '%s'", error_flags, + mysql_error(mysql)); + return -1; + } + break; + } + case ADMIN_FLUSH_USER_STATISTICS: + { + if (mysql_query(mysql,"flush user_statistics")) + { + my_printf_error(0, "flush failed; error: '%s'", error_flags, + mysql_error(mysql)); + return -1; + } + break; + } + case ADMIN_FLUSH_CLIENT_STATISTICS: + { + if (mysql_query(mysql,"flush client_statistics")) + { + my_printf_error(0, "flush failed; error: '%s'", error_flags, + mysql_error(mysql)); + return -1; + } + break; + } + case ADMIN_FLUSH_ALL_STATISTICS: + { + if (mysql_query(mysql, + "flush table_statistics,index_statistics," + "user_statistics,client_statistics")) + { + my_printf_error(0, "flush failed; error: '%s'", error_flags, + mysql_error(mysql)); + return -1; + } + break; + } + case ADMIN_FLUSH_ALL_STATUS: + { + if (mysql_query(mysql, + "flush status,table_statistics,index_statistics," + "user_statistics,client_statistics")) + { + my_printf_error(0, "flush failed; error: '%s'", error_flags, mysql_error(mysql)); return -1; } @@ -994,7 +1080,8 @@ static void print_version(void) static void usage(void) { print_version(); - puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc."); + puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc,\n" + "2009 Monty Program Ab"); puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"); puts("Administration program for the mysqld daemon."); printf("Usage: %s [OPTIONS] command command....\n", my_progname); @@ -1002,16 +1089,23 @@ static void usage(void) my_print_variables(my_long_options); print_defaults("my",load_default_groups); puts("\nWhere command is a one or more of: (Commands may be shortened)\n\ - create databasename Create a new database\n\ - debug Instruct server to write debug information to log\n\ - drop databasename Delete a database and all its tables\n\ - extended-status Gives an extended status message from the server\n\ - flush-hosts Flush all cached hosts\n\ - flush-logs Flush all logs\n\ - flush-status Clear status variables\n\ - flush-tables Flush all tables\n\ - flush-threads Flush the thread cache\n\ - flush-privileges Reload grant tables (same as reload)\n\ + create databasename Create a new database\n\ + debug Instruct server to write debug information to log\n\ + drop databasename Delete a database and all its tables\n\ + extended-status Gives an extended status message from the server\n\ + flush-all-statistics Flush all statistics tables\n\ + flush-all-status Flush status and statistics\n\ + flush-client-statistics Flush client statistics\n\ + flush-hosts Flush all cached hosts\n\ + flush-index-statistics Flush index statistics\n\ + flush-logs Flush all logs\n\ + flush-privileges Reload grant tables (same as reload)\n\ + flush-slow-log Flush slow query log\n\ + flush-status Clear status variables\n\ + flush-table-statistics Clear table statistics\n\ + flush-tables Flush all tables\n\ + flush-threads Flush the thread cache\n\ + flush-user-statistics Flush user statistics\n\ kill id,id,... Kill mysql threads"); #if MYSQL_VERSION_ID >= 32200 puts("\ === modified file 'configure.in' --- a/configure.in 2009-10-08 09:43:31 +0000 +++ b/configure.in 2009-10-19 17:14:48 +0000 @@ -829,7 +829,7 @@ AC_CHECK_HEADERS(fcntl.h fenv.h float.h sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \ unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \ sys/ioctl.h malloc.h sys/malloc.h sys/ipc.h sys/shm.h linux/config.h \ - sys/prctl.h sys/resource.h sys/param.h port.h ieeefp.h \ + sys/prctl.h sys/resource.h sys/param.h port.h ieeefp.h linux/unistd.h \ execinfo.h) AC_CHECK_HEADERS([xfs/xfs.h]) @@ -2096,7 +2096,18 @@ case "$target" in # We also disable for SCO for the time being, the headers for the # thread library we use conflicts with other headers. ;; - *) AC_CHECK_FUNCS(clock_gettime) +*) + # most systems require the program be linked with librt library to use + # the function clock_gettime + my_save_LIBS="$LIBS" + LIBS="" + AC_CHECK_LIB(rt,clock_gettime) + LIBRT=$LIBS + LIBS="$my_save_LIBS" + AC_SUBST(LIBRT) + + LIBS="$LIBS $LIBRT" + AC_CHECK_FUNCS(clock_gettime) ;; esac @@ -2786,7 +2797,7 @@ then fi sql_client_dirs="$sql_client_dirs client" -CLIENT_LIBS="$NON_THREADED_LIBS $openssl_libs $ZLIB_LIBS $STATIC_NSS_FLAGS" +CLIENT_LIBS="$NON_THREADED_LIBS $openssl_libs $ZLIB_LIBS $STATIC_NSS_FLAGS $LIBRT" AC_SUBST(CLIENT_LIBS) AC_SUBST(CLIENT_THREAD_LIBS) === modified file 'include/my_sys.h' --- a/include/my_sys.h 2009-09-07 20:50:10 +0000 +++ b/include/my_sys.h 2009-10-19 17:14:48 +0000 @@ -904,6 +904,7 @@ void my_free_open_file_info(void); extern time_t my_time(myf flags); extern ulonglong my_getsystime(void); +extern ulonglong my_getcputime(void); extern ulonglong my_micro_time(); extern ulonglong my_micro_time_and_time(time_t *time_arg); time_t my_time_possible_from_micro(ulonglong microtime); === modified file 'include/mysql_com.h' --- a/include/mysql_com.h 2008-10-10 15:28:41 +0000 +++ b/include/mysql_com.h 2009-10-19 17:14:48 +0000 @@ -29,6 +29,7 @@ #define SERVER_VERSION_LENGTH 60 #define SQLSTATE_LENGTH 5 +#define LIST_PROCESS_HOST_LEN 64 /* USER_HOST_BUFF_SIZE -- length of string buffer, that is enough to contain @@ -115,6 +116,11 @@ enum enum_server_command thread */ #define REFRESH_MASTER 128 /* Remove all bin logs in the index and truncate the index */ +#define REFRESH_TABLE_STATS 256 /* Refresh table stats hash table */ +#define REFRESH_INDEX_STATS 512 /* Refresh index stats hash table */ +#define REFRESH_USER_STATS 1024 /* Refresh user stats hash table */ +#define REFRESH_SLOW_QUERY_LOG 4096 /* Flush slow query log and rotate*/ +#define REFRESH_CLIENT_STATS 8192 /* Refresh client stats hash table */ /* The following can't be set with mysql_refresh() */ #define REFRESH_READ_LOCK 16384 /* Lock tables for read */ === modified file 'mysql-test/r/information_schema.result' --- a/mysql-test/r/information_schema.result 2009-09-29 20:19:43 +0000 +++ b/mysql-test/r/information_schema.result 2009-10-19 17:14:48 +0000 @@ -45,6 +45,7 @@ NOT (table_schema = 'INFORMATION_SCHEMA' select * from v1 ORDER BY c COLLATE utf8_bin; c CHARACTER_SETS +CLIENT_STATISTICS COLLATIONS COLLATION_CHARACTER_SET_APPLICABILITY COLUMNS @@ -54,6 +55,7 @@ EVENTS FILES GLOBAL_STATUS GLOBAL_VARIABLES +INDEX_STATISTICS INNODB_BUFFER_POOL_PAGES INNODB_BUFFER_POOL_PAGES_BLOB INNODB_BUFFER_POOL_PAGES_INDEX @@ -82,8 +84,10 @@ STATISTICS TABLES TABLE_CONSTRAINTS TABLE_PRIVILEGES +TABLE_STATISTICS TRIGGERS USER_PRIVILEGES +USER_STATISTICS VIEWS XTRADB_ENHANCEMENTS columns_priv @@ -121,6 +125,7 @@ c table_name TABLES TABLES TABLE_CONSTRAINTS TABLE_CONSTRAINTS TABLE_PRIVILEGES TABLE_PRIVILEGES +TABLE_STATISTICS TABLE_STATISTICS TRIGGERS TRIGGERS tables_priv tables_priv time_zone time_zone @@ -140,6 +145,7 @@ c table_name TABLES TABLES TABLE_CONSTRAINTS TABLE_CONSTRAINTS TABLE_PRIVILEGES TABLE_PRIVILEGES +TABLE_STATISTICS TABLE_STATISTICS TRIGGERS TRIGGERS tables_priv tables_priv time_zone time_zone @@ -159,6 +165,7 @@ c table_name TABLES TABLES TABLE_CONSTRAINTS TABLE_CONSTRAINTS TABLE_PRIVILEGES TABLE_PRIVILEGES +TABLE_STATISTICS TABLE_STATISTICS TRIGGERS TRIGGERS tables_priv tables_priv time_zone time_zone @@ -640,12 +647,13 @@ from information_schema.tables where table_schema='information_schema' limit 2; TABLE_NAME TABLE_TYPE ENGINE CHARACTER_SETS SYSTEM VIEW MEMORY -COLLATIONS SYSTEM VIEW MEMORY +CLIENT_STATISTICS SYSTEM VIEW MEMORY show tables from information_schema like "T%"; Tables_in_information_schema (T%) TABLES TABLE_CONSTRAINTS TABLE_PRIVILEGES +TABLE_STATISTICS TRIGGERS create database information_schema; ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' @@ -655,6 +663,7 @@ Tables_in_information_schema (T%) Table_ TABLES SYSTEM VIEW TABLE_CONSTRAINTS SYSTEM VIEW TABLE_PRIVILEGES SYSTEM VIEW +TABLE_STATISTICS SYSTEM VIEW TRIGGERS SYSTEM VIEW create table t1(a int); ERROR 42S02: Unknown table 't1' in information_schema @@ -667,6 +676,7 @@ Tables_in_information_schema (T%) TABLES TABLE_CONSTRAINTS TABLE_PRIVILEGES +TABLE_STATISTICS TRIGGERS select table_name from tables where table_name='user'; table_name @@ -856,6 +866,7 @@ TABLE_NAME COLUMN_NAME PRIVILEGES COLUMNS TABLE_NAME select COLUMN_PRIVILEGES TABLE_NAME select FILES TABLE_NAME select +INDEX_STATISTICS TABLE_NAME select KEY_COLUMN_USAGE TABLE_NAME select PARTITIONS TABLE_NAME select REFERENTIAL_CONSTRAINTS TABLE_NAME select @@ -863,6 +874,7 @@ STATISTICS TABLE_NAME select TABLES TABLE_NAME select TABLE_CONSTRAINTS TABLE_NAME select TABLE_PRIVILEGES TABLE_NAME select +TABLE_STATISTICS TABLE_NAME select VIEWS TABLE_NAME select INNODB_BUFFER_POOL_PAGES_INDEX table_name select INNODB_INDEX_STATS table_name select === modified file 'mysql-test/r/information_schema_all_engines.result' --- a/mysql-test/r/information_schema_all_engines.result 2009-08-03 20:09:53 +0000 +++ b/mysql-test/r/information_schema_all_engines.result 2009-10-19 17:14:48 +0000 @@ -2,6 +2,7 @@ use INFORMATION_SCHEMA; show tables; Tables_in_information_schema CHARACTER_SETS +CLIENT_STATISTICS COLLATIONS COLLATION_CHARACTER_SET_APPLICABILITY COLUMNS @@ -11,6 +12,7 @@ EVENTS FILES GLOBAL_STATUS GLOBAL_VARIABLES +INDEX_STATISTICS KEY_COLUMN_USAGE PARTITIONS PLUGINS @@ -26,8 +28,10 @@ STATISTICS TABLES TABLE_CONSTRAINTS TABLE_PRIVILEGES +TABLE_STATISTICS TRIGGERS USER_PRIVILEGES +USER_STATISTICS VIEWS INNODB_BUFFER_POOL_PAGES PBXT_STATISTICS @@ -60,6 +64,7 @@ c2.column_name LIKE '%SCHEMA%' ); table_name column_name CHARACTER_SETS CHARACTER_SET_NAME +CLIENT_STATISTICS CLIENT COLLATIONS COLLATION_NAME COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME COLUMNS TABLE_SCHEMA @@ -69,6 +74,7 @@ EVENTS EVENT_SCHEMA FILES TABLE_SCHEMA GLOBAL_STATUS VARIABLE_NAME GLOBAL_VARIABLES VARIABLE_NAME +INDEX_STATISTICS TABLE_SCHEMA KEY_COLUMN_USAGE CONSTRAINT_SCHEMA PARTITIONS TABLE_SCHEMA PLUGINS PLUGIN_NAME @@ -84,8 +90,10 @@ STATISTICS TABLE_SCHEMA TABLES TABLE_SCHEMA TABLE_CONSTRAINTS CONSTRAINT_SCHEMA TABLE_PRIVILEGES TABLE_SCHEMA +TABLE_STATISTICS TABLE_SCHEMA TRIGGERS TRIGGER_SCHEMA USER_PRIVILEGES GRANTEE +USER_STATISTICS USER VIEWS TABLE_SCHEMA INNODB_BUFFER_POOL_PAGES page_type PBXT_STATISTICS ID @@ -118,6 +126,7 @@ c2.column_name LIKE '%SCHEMA%' ); table_name column_name CHARACTER_SETS CHARACTER_SET_NAME +CLIENT_STATISTICS CLIENT COLLATIONS COLLATION_NAME COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME COLUMNS TABLE_SCHEMA @@ -127,6 +136,7 @@ EVENTS EVENT_SCHEMA FILES TABLE_SCHEMA GLOBAL_STATUS VARIABLE_NAME GLOBAL_VARIABLES VARIABLE_NAME +INDEX_STATISTICS TABLE_SCHEMA KEY_COLUMN_USAGE CONSTRAINT_SCHEMA PARTITIONS TABLE_SCHEMA PLUGINS PLUGIN_NAME @@ -142,8 +152,10 @@ STATISTICS TABLE_SCHEMA TABLES TABLE_SCHEMA TABLE_CONSTRAINTS CONSTRAINT_SCHEMA TABLE_PRIVILEGES TABLE_SCHEMA +TABLE_STATISTICS TABLE_SCHEMA TRIGGERS TRIGGER_SCHEMA USER_PRIVILEGES GRANTEE +USER_STATISTICS USER VIEWS TABLE_SCHEMA INNODB_BUFFER_POOL_PAGES page_type PBXT_STATISTICS ID @@ -182,6 +194,7 @@ group by c2.column_type order by num lim group by t.table_name order by num1, t.table_name; table_name group_concat(t.table_schema, '.', t.table_name) num1 CHARACTER_SETS information_schema.CHARACTER_SETS 1 +CLIENT_STATISTICS information_schema.CLIENT_STATISTICS 1 COLLATIONS information_schema.COLLATIONS 1 COLLATION_CHARACTER_SET_APPLICABILITY information_schema.COLLATION_CHARACTER_SET_APPLICABILITY 1 COLUMNS information_schema.COLUMNS 1 @@ -191,6 +204,7 @@ EVENTS information_schema.EVENTS 1 FILES information_schema.FILES 1 GLOBAL_STATUS information_schema.GLOBAL_STATUS 1 GLOBAL_VARIABLES information_schema.GLOBAL_VARIABLES 1 +INDEX_STATISTICS information_schema.INDEX_STATISTICS 1 INNODB_BUFFER_POOL_PAGES information_schema.INNODB_BUFFER_POOL_PAGES 1 INNODB_BUFFER_POOL_PAGES_BLOB information_schema.INNODB_BUFFER_POOL_PAGES_BLOB 1 INNODB_BUFFER_POOL_PAGES_INDEX information_schema.INNODB_BUFFER_POOL_PAGES_INDEX 1 @@ -220,8 +234,10 @@ STATISTICS information_schema.STATISTICS TABLES information_schema.TABLES 1 TABLE_CONSTRAINTS information_schema.TABLE_CONSTRAINTS 1 TABLE_PRIVILEGES information_schema.TABLE_PRIVILEGES 1 +TABLE_STATISTICS information_schema.TABLE_STATISTICS 1 TRIGGERS information_schema.TRIGGERS 1 USER_PRIVILEGES information_schema.USER_PRIVILEGES 1 +USER_STATISTICS information_schema.USER_STATISTICS 1 VIEWS information_schema.VIEWS 1 XTRADB_ENHANCEMENTS information_schema.XTRADB_ENHANCEMENTS 1 Database: information_schema @@ -229,6 +245,7 @@ Database: information_schema | Tables | +---------------------------------------+ | CHARACTER_SETS | +| CLIENT_STATISTICS | | COLLATIONS | | COLLATION_CHARACTER_SET_APPLICABILITY | | COLUMNS | @@ -238,6 +255,7 @@ Database: information_schema | FILES | | GLOBAL_STATUS | | GLOBAL_VARIABLES | +| INDEX_STATISTICS | | KEY_COLUMN_USAGE | | PARTITIONS | | PLUGINS | @@ -253,8 +271,10 @@ Database: information_schema | TABLES | | TABLE_CONSTRAINTS | | TABLE_PRIVILEGES | +| TABLE_STATISTICS | | TRIGGERS | | USER_PRIVILEGES | +| USER_STATISTICS | | VIEWS | | INNODB_BUFFER_POOL_PAGES | | PBXT_STATISTICS | @@ -277,6 +297,7 @@ Database: INFORMATION_SCHEMA | Tables | +---------------------------------------+ | CHARACTER_SETS | +| CLIENT_STATISTICS | | COLLATIONS | | COLLATION_CHARACTER_SET_APPLICABILITY | | COLUMNS | @@ -286,6 +307,7 @@ Database: INFORMATION_SCHEMA | FILES | | GLOBAL_STATUS | | GLOBAL_VARIABLES | +| INDEX_STATISTICS | | KEY_COLUMN_USAGE | | PARTITIONS | | PLUGINS | @@ -301,8 +323,10 @@ Database: INFORMATION_SCHEMA | TABLES | | TABLE_CONSTRAINTS | | TABLE_PRIVILEGES | +| TABLE_STATISTICS | | TRIGGERS | | USER_PRIVILEGES | +| USER_STATISTICS | | VIEWS | | INNODB_BUFFER_POOL_PAGES | | PBXT_STATISTICS | @@ -328,5 +352,5 @@ Wildcard: inf_rmation_schema +--------------------+ SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA; table_schema count(*) -information_schema 43 +information_schema 47 mysql 22 === modified file 'mysql-test/r/information_schema_db.result' --- a/mysql-test/r/information_schema_db.result 2009-09-07 20:50:10 +0000 +++ b/mysql-test/r/information_schema_db.result 2009-10-19 17:14:48 +0000 @@ -7,6 +7,7 @@ Tables_in_information_schema (T%) TABLES TABLE_CONSTRAINTS TABLE_PRIVILEGES +TABLE_STATISTICS TRIGGERS create database `inf%`; create database mbase; === modified file 'mysql-test/r/log_slow.result' --- a/mysql-test/r/log_slow.result 2009-09-03 14:05:38 +0000 +++ b/mysql-test/r/log_slow.result 2009-10-19 17:14:48 +0000 @@ -56,5 +56,6 @@ last_insert_id int(11) NO NULL insert_id int(11) NO NULL server_id int(10) unsigned NO NULL sql_text mediumtext NO NULL +flush slow query logs; set @@log_slow_filter=default; set @@log_slow_verbosity=default; === added file 'mysql-test/r/status_user.result' --- a/mysql-test/r/status_user.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/r/status_user.result 2009-10-19 17:14:48 +0000 @@ -0,0 +1,166 @@ +DROP TABLE IF EXISTS t1; +select variable_value from information_schema.global_status where variable_name="handler_read_key" into @global_read_key; +show columns from information_schema.client_statistics; +Field Type Null Key Default Extra +CLIENT varchar(64) NO +TOTAL_CONNECTIONS int(21) NO 0 +CONCURRENT_CONNECTIONS int(21) NO 0 +CONNECTED_TIME int(21) NO 0 +BUSY_TIME double NO 0 +CPU_TIME double NO 0 +BYTES_RECEIVED int(21) NO 0 +BYTES_SENT int(21) NO 0 +BINLOG_BYTES_WRITTEN int(21) NO 0 +ROWS_READ int(21) NO 0 +ROWS_SENT int(21) NO 0 +ROWS_DELETED int(21) NO 0 +ROWS_INSERTED int(21) NO 0 +ROWS_UPDATED int(21) NO 0 +SELECT_COMMANDS int(21) NO 0 +UPDATE_COMMANDS int(21) NO 0 +OTHER_COMMANDS int(21) NO 0 +COMMIT_TRANSACTIONS int(21) NO 0 +ROLLBACK_TRANSACTIONS int(21) NO 0 +DENIED_CONNECTIONS int(21) NO 0 +LOST_CONNECTIONS int(21) NO 0 +ACCESS_DENIED int(21) NO 0 +EMPTY_QUERIES int(21) NO 0 +show columns from information_schema.user_statistics; +Field Type Null Key Default Extra +USER varchar(48) NO +TOTAL_CONNECTIONS int(21) NO 0 +CONCURRENT_CONNECTIONS int(21) NO 0 +CONNECTED_TIME int(21) NO 0 +BUSY_TIME double NO 0 +CPU_TIME double NO 0 +BYTES_RECEIVED int(21) NO 0 +BYTES_SENT int(21) NO 0 +BINLOG_BYTES_WRITTEN int(21) NO 0 +ROWS_READ int(21) NO 0 +ROWS_SENT int(21) NO 0 +ROWS_DELETED int(21) NO 0 +ROWS_INSERTED int(21) NO 0 +ROWS_UPDATED int(21) NO 0 +SELECT_COMMANDS int(21) NO 0 +UPDATE_COMMANDS int(21) NO 0 +OTHER_COMMANDS int(21) NO 0 +COMMIT_TRANSACTIONS int(21) NO 0 +ROLLBACK_TRANSACTIONS int(21) NO 0 +DENIED_CONNECTIONS int(21) NO 0 +LOST_CONNECTIONS int(21) NO 0 +ACCESS_DENIED int(21) NO 0 +EMPTY_QUERIES int(21) NO 0 +show columns from information_schema.index_statistics; +Field Type Null Key Default Extra +TABLE_SCHEMA varchar(192) NO +TABLE_NAME varchar(192) NO +INDEX_NAME varchar(192) NO +ROWS_READ int(21) NO 0 +show columns from information_schema.table_statistics; +Field Type Null Key Default Extra +TABLE_SCHEMA varchar(192) NO +TABLE_NAME varchar(192) NO +ROWS_READ int(21) NO 0 +ROWS_CHANGED int(21) NO 0 +ROWS_CHANGED_X_INDEXES int(21) NO 0 +set @save_general_log=@@global.general_log; +set @@global.general_log=0; +set @@global.userstat=1; +flush status; +create table t1 (a int, primary key (a), b int default 0) engine=myisam; +insert into t1 (a) values (1),(2),(3),(4); +update t1 set b=1; +update t1 set b=5 where a=2; +delete from t1 where a=3; +/* Empty query */ +select * from t1 where a=999; +a b +drop table t1; +create table t1 (a int, primary key (a), b int default 0) engine=innodb; +begin; +insert into t1 values(1,1); +commit; +begin; +insert into t1 values(2,2); +commit; +begin; +insert into t1 values(3,3); +rollback; +drop table t1; +select sleep(1); +sleep(1) +0 +show status like "rows%"; +Variable_name Value +Rows_read 6 +Rows_sent 1 +show status like "ha%"; +Variable_name Value +Handler_commit 10 +Handler_delete 1 +Handler_discover 0 +Handler_prepare 10 +Handler_read_first 0 +Handler_read_key 3 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 5 +Handler_rollback 2 +Handler_savepoint 0 +Handler_savepoint_rollback 0 +Handler_update 5 +Handler_write 7 +select variable_value - @global_read_key as "handler_read_key" from information_schema.global_status where variable_name="handler_read_key"; +handler_read_key +3 +set @@global.userstat=0; +select * from information_schema.index_statistics; +TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ +test t1 PRIMARY 2 +select * from information_schema.table_statistics; +TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES +test t1 6 13 13 +show table_statistics; +Table_schema Table_name Rows_read Rows_changed Rows_changed_x_#indexes +test t1 6 13 13 +show index_statistics; +Table_schema Table_name Index_name Rows_read +test t1 PRIMARY 2 +select TOTAL_CONNECTIONS, CONCURRENT_CONNECTIONS, ROWS_READ, ROWS_SENT, +ROWS_DELETED, ROWS_INSERTED, ROWS_UPDATED, SELECT_COMMANDS, +UPDATE_COMMANDS, OTHER_COMMANDS, COMMIT_TRANSACTIONS, +ROLLBACK_TRANSACTIONS, DENIED_CONNECTIONS, LOST_CONNECTIONS, +ACCESS_DENIED, EMPTY_QUERIES from information_schema.client_statistics; +TOTAL_CONNECTIONS CONCURRENT_CONNECTIONS ROWS_READ ROWS_SENT ROWS_DELETED ROWS_INSERTED ROWS_UPDATED SELECT_COMMANDS UPDATE_COMMANDS OTHER_COMMANDS COMMIT_TRANSACTIONS ROLLBACK_TRANSACTIONS DENIED_CONNECTIONS LOST_CONNECTIONS ACCESS_DENIED EMPTY_QUERIES +1 0 6 2 1 8 5 3 11 9 10 2 0 0 0 1 +select TOTAL_CONNECTIONS, CONCURRENT_CONNECTIONS, ROWS_READ, ROWS_SENT, +ROWS_DELETED, ROWS_INSERTED, ROWS_UPDATED, SELECT_COMMANDS, +UPDATE_COMMANDS, OTHER_COMMANDS, COMMIT_TRANSACTIONS, +ROLLBACK_TRANSACTIONS, DENIED_CONNECTIONS, LOST_CONNECTIONS, +ACCESS_DENIED, EMPTY_QUERIES from information_schema.user_statistics; +TOTAL_CONNECTIONS CONCURRENT_CONNECTIONS ROWS_READ ROWS_SENT ROWS_DELETED ROWS_INSERTED ROWS_UPDATED SELECT_COMMANDS UPDATE_COMMANDS OTHER_COMMANDS COMMIT_TRANSACTIONS ROLLBACK_TRANSACTIONS DENIED_CONNECTIONS LOST_CONNECTIONS ACCESS_DENIED EMPTY_QUERIES +1 0 6 2 1 8 5 3 11 9 10 2 0 0 0 1 +flush table_statistics; +flush index_statistics; +select * from information_schema.index_statistics; +TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ +select * from information_schema.table_statistics; +TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES +show status like "%statistics%"; +Variable_name Value +Com_show_client_statistics 0 +Com_show_index_statistics 1 +Com_show_table_statistics 1 +Com_show_user_statistics 0 +select connected_time <> 0, busy_time <> 0, bytes_received <> 0, +bytes_sent <> 0, binlog_bytes_written <> 0 +from information_schema.user_statistics; +connected_time <> 0 busy_time <> 0 bytes_received <> 0 bytes_sent <> 0 binlog_bytes_written <> 0 +1 1 1 1 1 +select connected_time <> 0, busy_time <> 0, bytes_received <> 0, +bytes_sent <> 0, binlog_bytes_written <> 0 +from information_schema.client_statistics; +connected_time <> 0 busy_time <> 0 bytes_received <> 0 bytes_sent <> 0 binlog_bytes_written <> 0 +1 1 1 1 1 +set @@global.general_log=@save_general_log; === modified file 'mysql-test/t/log_slow.test' --- a/mysql-test/t/log_slow.test 2009-09-03 14:05:38 +0000 +++ b/mysql-test/t/log_slow.test 2009-10-19 17:14:48 +0000 @@ -36,6 +36,12 @@ select @@log_slow_verbosity; show fields from mysql.slow_log; +# +# Check flush command +# + +flush slow query logs; + # Reset used variables set @@log_slow_filter=default; === added file 'mysql-test/t/status_user-master.opt' --- a/mysql-test/t/status_user-master.opt 1970-01-01 00:00:00 +0000 +++ b/mysql-test/t/status_user-master.opt 2009-10-19 17:14:48 +0000 @@ -0,0 +1 @@ +--force-restart === added file 'mysql-test/t/status_user.test' --- a/mysql-test/t/status_user.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/t/status_user.test 2009-10-19 17:14:48 +0000 @@ -0,0 +1,97 @@ +# +# Testing of user status (the userstat variable). +# Note that this test requires a fresh restart to not problems with +# old status + +-- source include/have_innodb.inc +-- source include/have_log_bin.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +select variable_value from information_schema.global_status where variable_name="handler_read_key" into @global_read_key; +show columns from information_schema.client_statistics; +show columns from information_schema.user_statistics; +show columns from information_schema.index_statistics; +show columns from information_schema.table_statistics; + +# Disable logging to get right number of writes into the tables. +set @save_general_log=@@global.general_log; +set @@global.general_log=0; +set @@global.userstat=1; +flush status; + +create table t1 (a int, primary key (a), b int default 0) engine=myisam; +insert into t1 (a) values (1),(2),(3),(4); +update t1 set b=1; +update t1 set b=5 where a=2; +delete from t1 where a=3; + +/* Empty query */ +select * from t1 where a=999; + +drop table t1; + +# +# Test the commit and rollback are counted +# + +create table t1 (a int, primary key (a), b int default 0) engine=innodb; +begin; +insert into t1 values(1,1); +commit; +begin; +insert into t1 values(2,2); +commit; +begin; +insert into t1 values(3,3); +rollback; +drop table t1; + +select sleep(1); + +show status like "rows%"; +show status like "ha%"; +select variable_value - @global_read_key as "handler_read_key" from information_schema.global_status where variable_name="handler_read_key"; + +# Ensure that the following commands doesn't change statistics + +set @@global.userstat=0; + +# +# Check that we got right statistics +# +select * from information_schema.index_statistics; +select * from information_schema.table_statistics; +show table_statistics; +show index_statistics; +select TOTAL_CONNECTIONS, CONCURRENT_CONNECTIONS, ROWS_READ, ROWS_SENT, + ROWS_DELETED, ROWS_INSERTED, ROWS_UPDATED, SELECT_COMMANDS, + UPDATE_COMMANDS, OTHER_COMMANDS, COMMIT_TRANSACTIONS, + ROLLBACK_TRANSACTIONS, DENIED_CONNECTIONS, LOST_CONNECTIONS, + ACCESS_DENIED, EMPTY_QUERIES from information_schema.client_statistics; +select TOTAL_CONNECTIONS, CONCURRENT_CONNECTIONS, ROWS_READ, ROWS_SENT, + ROWS_DELETED, ROWS_INSERTED, ROWS_UPDATED, SELECT_COMMANDS, + UPDATE_COMMANDS, OTHER_COMMANDS, COMMIT_TRANSACTIONS, + ROLLBACK_TRANSACTIONS, DENIED_CONNECTIONS, LOST_CONNECTIONS, + ACCESS_DENIED, EMPTY_QUERIES from information_schema.user_statistics; +flush table_statistics; +flush index_statistics; +select * from information_schema.index_statistics; +select * from information_schema.table_statistics; +show status like "%statistics%"; + +# +# Test that some variables are not 0 +# + +select connected_time <> 0, busy_time <> 0, bytes_received <> 0, + bytes_sent <> 0, binlog_bytes_written <> 0 + from information_schema.user_statistics; +select connected_time <> 0, busy_time <> 0, bytes_received <> 0, + bytes_sent <> 0, binlog_bytes_written <> 0 + from information_schema.client_statistics; + +# Cleanup +set @@global.general_log=@save_general_log; === modified file 'mysys/my_getsystime.c' --- a/mysys/my_getsystime.c 2008-04-28 16:24:05 +0000 +++ b/mysys/my_getsystime.c 2009-10-19 17:14:48 +0000 @@ -28,6 +28,10 @@ #ifdef __NETWARE__ #include <nks/time.h> #endif +#ifdef HAVE_LINUX_UNISTD_H +#include <linux/unistd.h> +#endif + ulonglong my_getsystime() { @@ -222,3 +226,25 @@ time_t my_time_possible_from_micro(ulong return (time_t) (microtime / 1000000); #endif /* defined(__WIN__) */ } + + +/* + Return cpu time in milliseconds * 10 +*/ + +ulonglong my_getcputime() +{ +#ifdef HAVE_CLOCK_GETTIME + struct timespec tp; + if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)) + return 0; + return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100; +#elif defined(__NR_clock_gettime) + struct timespec tp; + if (syscall(__NR_clock_gettime, CLOCK_THREAD_CPUTIME_ID, &tp)) + return 0; + return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100; +#else + return 0; +#endif /* HAVE_CLOCK_GETTIME */ +} === modified file 'sql/authors.h' --- a/sql/authors.h 2007-03-16 06:39:07 +0000 +++ b/sql/authors.h 2009-10-19 17:14:48 +0000 @@ -34,23 +34,35 @@ struct show_table_authors_st { */ struct show_table_authors_st show_table_authors[]= { + { "Michael (Monty) Widenius", "Tusby, Finland", + "Lead developer and main author" }, + { "David Axmark", "London, England", + "MySQL founder; Small stuff long time ago, Monty ripped it out!" }, + { "Sergei Golubchik", "Kerpen, Germany", + "Full-text search, precision math" }, + { "Igor Babaev", "Bellevue, USA", "Optimizer, keycache, core work"}, + { "Sergey Petrunia", "St. Petersburg, Russia", "Optimizer"}, + { "Oleksandr Byelkin", "Lugansk, Ukraine", + "Query Cache (4.0), Subqueries (4.1), Views (5.0)" }, { "Brian (Krow) Aker", "Seattle, WA, USA", "Architecture, archive, federated, bunch of little stuff :)" }, - { "Venu Anuganti", "", "Client/server protocol (4.1)" }, - { "David Axmark", "Uppsala, Sweden", - "Small stuff long time ago, Monty ripped it out!" }, + { "Kristian Nielsen", "Copenhagen, Denmark", + "General build stuff," }, { "Alexander (Bar) Barkov", "Izhevsk, Russia", "Unicode and character sets (4.1)" }, + { "Guilhem Bichot", "Bordeaux, France", "Replication (since 4.0)" }, + { "Venu Anuganti", "", "Client/server protocol (4.1)" }, + { "Konstantin Osipov", "Moscow, Russia", + "Prepared statements (4.1), Cursors (5.0)" }, + { "Dmitri Lenev", "Moscow, Russia", + "Time zones support (4.1), Triggers (5.0)" }, { "Omer BarNir", "Sunnyvale, CA, USA", "Testing (sometimes) and general QA stuff" }, - { "Guilhem Bichot", "Bordeaux, France", "Replication (since 4.0)" }, { "John Birrell", "", "Emulation of pthread_mutex() for OS/2" }, { "Andreas F. Bobak", "", "AGGREGATE extension to user-defined functions" }, { "Alexey Botchkov (Holyfoot)", "Izhevsk, Russia", "GIS extensions (4.1), embedded server (4.1), precision math (5.0)"}, { "Reggie Burnett", "Nashville, TN, USA", "Windows development, Connectors" }, - { "Oleksandr Byelkin", "Lugansk, Ukraine", - "Query Cache (4.0), Subqueries (4.1), Views (5.0)" }, { "Kent Boortz", "Orebro, Sweden", "Test platform, and general build stuff" }, { "Tim Bunce", "", "mysqlhotcopy" }, { "Yves Carlier", "", "mysqlaccess" }, @@ -67,8 +79,6 @@ struct show_table_authors_st show_table_ { "Yuri Dario", "", "OS/2 port" }, { "Andrei Elkin", "Espoo, Finland", "Replication" }, { "Patrick Galbraith", "Sharon, NH", "Federated Engine, mysqlslap" }, - { "Sergei Golubchik", "Kerpen, Germany", - "Full-text search, precision math" }, { "Lenz Grimmer", "Hamburg, Germany", "Production (build and release) engineering" }, { "Nikolay Grishakin", "Austin, TX, USA", "Testing - Server" }, @@ -83,8 +93,6 @@ struct show_table_authors_st show_table_ { "Hakan K������ky��lmaz", "Walldorf, Germany", "Testing - Server" }, { "Greg (Groggy) Lehey", "Uchunga, SA, Australia", "Backup" }, { "Matthias Leich", "Berlin, Germany", "Testing - Server" }, - { "Dmitri Lenev", "Moscow, Russia", - "Time zones support (4.1), Triggers (5.0)" }, { "Arjen Lentz", "Brisbane, Australia", "Documentation (2001-2004), Dutch error messages, LOG2()" }, { "Marc Liyanage", "", "Created Mac OS X packages" }, @@ -96,8 +104,6 @@ struct show_table_authors_st show_table_ { "Jonathan (Jeb) Miller", "Kyle, TX, USA", "Testing - Cluster, Replication" }, { "Elliot Murphy", "Cocoa, FL, USA", "Replication and backup" }, - { "Kristian Nielsen", "Copenhagen, Denmark", - "General build stuff" }, { "Pekka Nouisiainen", "Stockholm, Sweden", "NDB Cluster: BLOB support, character set support, ordered indexes" }, { "Alexander Nozdrin", "Moscow, Russia", @@ -105,8 +111,6 @@ struct show_table_authors_st show_table_ { "Per Eric Olsson", "", "Testing of dynamic record format" }, { "Jonas Oreland", "Stockholm, Sweden", "NDB Cluster, Online Backup, lots of other things" }, - { "Konstantin Osipov", "Moscow, Russia", - "Prepared statements (4.1), Cursors (5.0)" }, { "Alexander (Sasha) Pachev", "Provo, UT, USA", "Statement-based replication, SHOW CREATE TABLE, mysql-bench" }, { "Irena Pancirov", "", "Port to Windows with Borland compiler" }, @@ -144,9 +148,9 @@ struct show_table_authors_st show_table_ { "Sergey Vojtovich", "Izhevsk, Russia", "Plugins infrastructure (5.1)" }, { "Matt Wagner", "Northfield, MN, USA", "Bug fixing" }, { "Jim Winstead Jr.", "Los Angeles, CA, USA", "Bug fixing" }, - { "Michael (Monty) Widenius", "Tusby, Finland", - "Lead developer and main author" }, { "Peter Zaitsev", "Tacoma, WA, USA", "SHA1(), AES_ENCRYPT(), AES_DECRYPT(), bug fixing" }, + {"Mark Mark Callaghan", "Texas, USA", "Statistics patches"}, + {"Percona", "CA, USA", "Microslow patches"}, {NULL, NULL, NULL} }; === modified file 'sql/event_data_objects.cc' --- a/sql/event_data_objects.cc 2009-09-15 10:46:35 +0000 +++ b/sql/event_data_objects.cc 2009-10-19 17:14:48 +0000 @@ -1366,7 +1366,7 @@ Event_job_data::execute(THD *thd, bool d DBUG_ENTER("Event_job_data::execute"); - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, 0); /* MySQL parser currently assumes that current database is either === modified file 'sql/event_db_repository.cc' --- a/sql/event_db_repository.cc 2009-02-15 10:58:34 +0000 +++ b/sql/event_db_repository.cc 2009-10-19 17:14:48 +0000 @@ -404,17 +404,18 @@ Event_db_repository::index_read_for_db_f } key_copy(key_buf, event_table->record[0], key_info, key_len); - if (!(ret= event_table->file->index_read_map(event_table->record[0], key_buf, - (key_part_map)1, - HA_READ_PREFIX))) + if (!(ret= event_table->file->ha_index_read_map(event_table->record[0], + key_buf, + (key_part_map)1, + HA_READ_PREFIX))) { DBUG_PRINT("info",("Found rows. Let's retrieve them. ret=%d", ret)); do { ret= copy_event_to_schema_table(thd, schema_table, event_table); if (ret == 0) - ret= event_table->file->index_next_same(event_table->record[0], - key_buf, key_len); + ret= event_table->file->ha_index_next_same(event_table->record[0], + key_buf, key_len); } while (ret == 0); } DBUG_PRINT("info", ("Scan finished. ret=%d", ret)); @@ -883,8 +884,9 @@ Event_db_repository::find_named_event(LE key_copy(key, table->record[0], table->key_info, table->key_info->key_length); - if (table->file->index_read_idx_map(table->record[0], 0, key, HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + if (table->file->ha_index_read_idx_map(table->record[0], 0, key, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) { DBUG_PRINT("info", ("Row not found")); DBUG_RETURN(TRUE); === modified file 'sql/filesort.cc' --- a/sql/filesort.cc 2009-09-03 14:05:38 +0000 +++ b/sql/filesort.cc 2009-10-19 17:14:48 +0000 @@ -577,11 +577,11 @@ static ha_rows find_all_keys(SORTPARAM * error= my_errno ? my_errno : -1; /* Abort */ break; } - error=file->rnd_pos(sort_form->record[0],next_pos); + error=file->ha_rnd_pos(sort_form->record[0],next_pos); } else { - error=file->rnd_next(sort_form->record[0]); + error=file->ha_rnd_next(sort_form->record[0]); if (!flag) { my_store_ptr(ref_pos,ref_length,record); // Position to row === modified file 'sql/ha_partition.cc' --- a/sql/ha_partition.cc 2009-09-07 20:50:10 +0000 +++ b/sql/ha_partition.cc 2009-10-19 17:14:48 +0000 @@ -1636,7 +1636,7 @@ int ha_partition::copy_partitions(ulongl goto error; while (TRUE) { - if ((result= file->rnd_next(m_rec0))) + if ((result= file->ha_rnd_next(m_rec0))) { if (result == HA_ERR_RECORD_DELETED) continue; //Probably MyISAM @@ -3495,7 +3495,7 @@ int ha_partition::rnd_next(uchar *buf) while (TRUE) { - result= file->rnd_next(buf); + result= file->ha_rnd_next(buf); if (!result) { m_last_part= part_id; @@ -4345,8 +4345,8 @@ int ha_partition::handle_unordered_next( } else if (is_next_same) { - if (!(error= file->index_next_same(buf, m_start_key.key, - m_start_key.length))) + if (!(error= file->ha_index_next_same(buf, m_start_key.key, + m_start_key.length))) { m_last_part= m_part_spec.start_part; DBUG_RETURN(0); @@ -4354,7 +4354,7 @@ int ha_partition::handle_unordered_next( } else { - if (!(error= file->index_next(buf))) + if (!(error= file->ha_index_next(buf))) { m_last_part= m_part_spec.start_part; DBUG_RETURN(0); // Row was in range @@ -4409,24 +4409,26 @@ int ha_partition::handle_unordered_scan_ break; case partition_index_read: DBUG_PRINT("info", ("index_read on partition %d", i)); - error= file->index_read_map(buf, m_start_key.key, - m_start_key.keypart_map, - m_start_key.flag); + error= file->ha_index_read_map(buf, m_start_key.key, + m_start_key.keypart_map, + m_start_key.flag); break; case partition_index_first: DBUG_PRINT("info", ("index_first on partition %d", i)); - /* MyISAM engine can fail if we call index_first() when indexes disabled */ - /* that happens if the table is empty. */ - /* Here we use file->stats.records instead of file->records() because */ - /* file->records() is supposed to return an EXACT count, and it can be */ - /* possibly slow. We don't need an exact number, an approximate one- from*/ - /* the last ::info() call - is sufficient. */ + /* + MyISAM engine can fail if we call index_first() when indexes disabled + that happens if the table is empty. + Here we use file->stats.records instead of file->records() because + file->records() is supposed to return an EXACT count, and it can be + possibly slow. We don't need an exact number, an approximate one- from + the last ::info() call - is sufficient. + */ if (file->stats.records == 0) { error= HA_ERR_END_OF_FILE; break; } - error= file->index_first(buf); + error= file->ha_index_first(buf); break; case partition_index_first_unordered: /* @@ -4507,45 +4509,49 @@ int ha_partition::handle_ordered_index_s switch (m_index_scan_type) { case partition_index_read: - error= file->index_read_map(rec_buf_ptr, - m_start_key.key, - m_start_key.keypart_map, - m_start_key.flag); + error= file->ha_index_read_map(rec_buf_ptr, + m_start_key.key, + m_start_key.keypart_map, + m_start_key.flag); break; case partition_index_first: - /* MyISAM engine can fail if we call index_first() when indexes disabled */ - /* that happens if the table is empty. */ - /* Here we use file->stats.records instead of file->records() because */ - /* file->records() is supposed to return an EXACT count, and it can be */ - /* possibly slow. We don't need an exact number, an approximate one- from*/ - /* the last ::info() call - is sufficient. */ + /* + MyISAM engine can fail if we call index_first() when indexes disabled + that happens if the table is empty. + Here we use file->stats.records instead of file->records() because + file->records() is supposed to return an EXACT count, and it can be + possibly slow. We don't need an exact number, an approximate one- from + the last ::info() call - is sufficient. + */ if (file->stats.records == 0) { error= HA_ERR_END_OF_FILE; break; } - error= file->index_first(rec_buf_ptr); + error= file->ha_index_first(rec_buf_ptr); reverse_order= FALSE; break; case partition_index_last: - /* MyISAM engine can fail if we call index_last() when indexes disabled */ - /* that happens if the table is empty. */ - /* Here we use file->stats.records instead of file->records() because */ - /* file->records() is supposed to return an EXACT count, and it can be */ - /* possibly slow. We don't need an exact number, an approximate one- from*/ - /* the last ::info() call - is sufficient. */ + /* + MyISAM engine can fail if we call index_last() when indexes disabled + that happens if the table is empty. + Here we use file->stats.records instead of file->records() because + file->records() is supposed to return an EXACT count, and it can be + possibly slow. We don't need an exact number, an approximate one- from + the last ::info() call - is sufficient. + */ if (file->stats.records == 0) { error= HA_ERR_END_OF_FILE; break; } - error= file->index_last(rec_buf_ptr); + error= file->ha_index_last(rec_buf_ptr); reverse_order= TRUE; break; case partition_index_read_last: - error= file->index_read_last_map(rec_buf_ptr, - m_start_key.key, - m_start_key.keypart_map); + error= file->ha_index_read_last_map(rec_buf_ptr, + m_start_key.key, + m_start_key.keypart_map); reverse_order= TRUE; break; case partition_read_range: @@ -4647,10 +4653,10 @@ int ha_partition::handle_ordered_next(uc memcpy(rec_buf(part_id), table->record[0], m_rec_length); } else if (!is_next_same) - error= file->index_next(rec_buf(part_id)); + error= file->ha_index_next(rec_buf(part_id)); else - error= file->index_next_same(rec_buf(part_id), m_start_key.key, - m_start_key.length); + error= file->ha_index_next_same(rec_buf(part_id), m_start_key.key, + m_start_key.length); if (error) { if (error == HA_ERR_END_OF_FILE) @@ -4695,7 +4701,7 @@ int ha_partition::handle_ordered_prev(uc handler *file= m_file[part_id]; DBUG_ENTER("ha_partition::handle_ordered_prev"); - if ((error= file->index_prev(rec_buf(part_id)))) + if ((error= file->ha_index_prev(rec_buf(part_id)))) { if (error == HA_ERR_END_OF_FILE) { === modified file 'sql/handler.cc' --- a/sql/handler.cc 2009-09-09 21:06:57 +0000 +++ b/sql/handler.cc 2009-10-19 17:14:48 +0000 @@ -1236,6 +1236,7 @@ int ha_commit_one_phase(THD *thd, bool a my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); error=1; } + /* Should this be done only if is_real_trans is set ? */ status_var_increment(thd->status_var.ha_commit_count); ha_info_next= ha_info->next(); ha_info->reset(); /* keep it conveniently zero-filled */ @@ -2092,6 +2093,8 @@ int handler::ha_open(TABLE *table_arg, c dup_ref=ref+ALIGN_SIZE(ref_length); cached_table_flags= table_flags(); } + rows_read= rows_changed= 0; + memset(index_rows_read, 0, sizeof(index_rows_read)); DBUG_RETURN(error); } @@ -2513,9 +2516,10 @@ void handler::get_auto_increment(ulonglo key_copy(key, table->record[0], table->key_info + table->s->next_number_index, table->s->next_number_key_offset); - error= index_read_map(table->record[1], key, - make_prev_keypart_map(table->s->next_number_keypart), - HA_READ_PREFIX_LAST); + error= ha_index_read_map(table->record[1], key, + make_prev_keypart_map(table->s-> + next_number_keypart), + HA_READ_PREFIX_LAST); /* MySQL needs to call us for next row: assume we are inserting ("a",null) here, we return 3, and next this statement will want to insert @@ -3549,6 +3553,122 @@ void handler::get_dynamic_partition_info } +/* + Updates the global table stats with the TABLE this handler represents +*/ + +void handler::update_global_table_stats() +{ + TABLE_STATS * table_stats; + + status_var_add(table->in_use->status_var.rows_read, rows_read); + + if (!table->in_use->userstat_running) + { + rows_read= rows_changed= 0; + return; + } + + if (rows_read + rows_changed == 0) + return; // Nothing to update. + + DBUG_ASSERT(table->s && table->s->table_cache_key.str); + + pthread_mutex_lock(&LOCK_global_table_stats); + /* Gets the global table stats, creating one if necessary. */ + if (!(table_stats= (TABLE_STATS*) + hash_search(&global_table_stats, + (uchar*) table->s->table_cache_key.str, + table->s->table_cache_key.length))) + { + if (!(table_stats = ((TABLE_STATS*) + my_malloc(sizeof(TABLE_STATS), + MYF(MY_WME | MY_ZEROFILL))))) + { + /* Out of memory error already given */ + goto end; + } + memcpy(table_stats->table, table->s->table_cache_key.str, + table->s->table_cache_key.length); + table_stats->table_name_length= table->s->table_cache_key.length; + table_stats->engine_type= ht->db_type; + /* No need to set variables to 0, as we use MY_ZEROFILL above */ + + if (my_hash_insert(&global_table_stats, (uchar*) table_stats)) + { + /* Out of memory error is already given */ + my_free(table_stats, 0); + goto end; + } + } + // Updates the global table stats. + table_stats->rows_read+= rows_read; + table_stats->rows_changed+= rows_changed; + table_stats->rows_changed_x_indexes+= (rows_changed * + (table->s->keys ? table->s->keys : + 1)); + rows_read= rows_changed= 0; +end: + pthread_mutex_unlock(&LOCK_global_table_stats); +} + + +/* + Updates the global index stats with this handler's accumulated index reads. +*/ + +void handler::update_global_index_stats() +{ + DBUG_ASSERT(table->s); + + if (!table->in_use->userstat_running) + { + /* Reset all index read values */ + bzero(index_rows_read, sizeof(index_rows_read[0]) * table->s->keys); + return; + } + + for (uint index = 0; index < table->s->keys; index++) + { + if (index_rows_read[index]) + { + INDEX_STATS* index_stats; + uint key_length; + KEY *key_info = &table->key_info[index]; // Rows were read using this + + DBUG_ASSERT(key_info->cache_name); + if (!key_info->cache_name) + continue; + key_length= table->s->table_cache_key.length + key_info->name_length + 1; + pthread_mutex_lock(&LOCK_global_index_stats); + // Gets the global index stats, creating one if necessary. + if (!(index_stats= (INDEX_STATS*) hash_search(&global_index_stats, + key_info->cache_name, + key_length))) + { + if (!(index_stats = ((INDEX_STATS*) + my_malloc(sizeof(INDEX_STATS), + MYF(MY_WME | MY_ZEROFILL))))) + goto end; // Error is already given + + memcpy(index_stats->index, key_info->cache_name, key_length); + index_stats->index_name_length= key_length; + if (my_hash_insert(&global_index_stats, (uchar*) index_stats)) + { + my_free(index_stats, 0); + goto end; + } + } + /* Updates the global index stats. */ + index_stats->rows_read+= index_rows_read[index]; + index_rows_read[index]= 0; +end: + pthread_mutex_unlock(&LOCK_global_index_stats); + } + } +} + + /**************************************************************************** ** Some general functions that isn't in the handler class ****************************************************************************/ @@ -4207,17 +4327,16 @@ int handler::read_range_first(const key_ range_key_part= table->key_info[active_index].key_part; if (!start_key) // Read first record - result= index_first(table->record[0]); + result= ha_index_first(table->record[0]); else - result= index_read_map(table->record[0], - start_key->key, - start_key->keypart_map, - start_key->flag); + result= ha_index_read_map(table->record[0], + start_key->key, + start_key->keypart_map, + start_key->flag); if (result) DBUG_RETURN((result == HA_ERR_KEY_NOT_FOUND) ? HA_ERR_END_OF_FILE : result); - DBUG_RETURN (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE); } @@ -4243,11 +4362,11 @@ int handler::read_range_next() if (eq_range) { /* We trust that index_next_same always gives a row in range */ - DBUG_RETURN(index_next_same(table->record[0], - end_range->key, - end_range->length)); + DBUG_RETURN(ha_index_next_same(table->record[0], + end_range->key, + end_range->length)); } - result= index_next(table->record[0]); + result= ha_index_next(table->record[0]); if (result) DBUG_RETURN(result); DBUG_RETURN(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE); @@ -4629,6 +4748,7 @@ int handler::ha_write_row(uchar *buf) if (unlikely(error= write_row(buf))) DBUG_RETURN(error); + rows_changed++; if (unlikely(error= binlog_log_row(table, 0, buf, log_func))) DBUG_RETURN(error); /* purecov: inspected */ DBUG_RETURN(0); @@ -4650,6 +4770,7 @@ int handler::ha_update_row(const uchar * if (unlikely(error= update_row(old_data, new_data))) return error; + rows_changed++; if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func))) return error; return 0; @@ -4664,6 +4785,7 @@ int handler::ha_delete_row(const uchar * if (unlikely(error= delete_row(buf))) return error; + rows_changed++; if (unlikely(error= binlog_log_row(table, buf, 0, log_func))) return error; return 0; === modified file 'sql/handler.h' --- a/sql/handler.h 2009-09-07 20:50:10 +0000 +++ b/sql/handler.h 2009-10-19 17:14:48 +0000 @@ -30,6 +30,10 @@ #define USING_TRANSACTIONS +#if MAX_KEY > 128 +#error MAX_KEY is too large. Values up to 128 are supported. +#endif + // the following is for checking tables #define HA_ADMIN_ALREADY_DONE 1 @@ -601,8 +605,9 @@ struct handlerton SHOW_COMP_OPTION state; /* - Historical number used for frm file to determine the correct storage engine. - This is going away and new engines will just use "name" for this. + Historical number used for frm file to determine the correct + storage engine. This is going away and new engines will just use + "name" for this. */ enum legacy_db_type db_type; /* @@ -1138,6 +1143,12 @@ public: Interval returned by get_auto_increment() and being consumed by the inserter. */ + /* Statistics variables */ + ulonglong rows_read; + ulonglong rows_changed; + /* One bigger than needed to avoid to test if key == MAX_KEY */ + ulonglong index_rows_read[MAX_KEY+1]; + Discrete_interval auto_inc_interval_for_cur_row; /** Number of reserved auto-increment intervals. Serves as a heuristic @@ -1156,7 +1167,10 @@ public: locked(FALSE), implicit_emptied(0), pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0), auto_inc_intervals_count(0) - {} + { + reset_statistics(); + } + virtual ~handler(void) { DBUG_ASSERT(locked == FALSE); @@ -1278,10 +1292,16 @@ public: virtual void print_error(int error, myf errflag); virtual bool get_error_message(int error, String *buf); uint get_dup_key(int error); + void reset_statistics() + { + rows_read= rows_changed= 0; + bzero(index_rows_read, sizeof(index_rows_read)); + } virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share) { table= table_arg; table_share= share; + reset_statistics(); } virtual double scan_time() { return ulonglong2double(stats.data_file_length) / IO_SIZE + 2; } @@ -1390,22 +1410,23 @@ public: } /** @brief - Positions an index cursor to the index specified in the handle. Fetches the - row if available. If the key value is null, begin at the first key of the - index. + Positions an index cursor to the index specified in the + handle. Fetches the row if available. If the key value is null, + begin at the first key of the index. */ +protected: virtual int index_read_map(uchar * buf, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag) { uint key_len= calculate_key_len(table, active_index, key, keypart_map); - return index_read(buf, key, key_len, find_flag); + return index_read(buf, key, key_len, find_flag); } /** @brief - Positions an index cursor to the index specified in the handle. Fetches the - row if available. If the key value is null, begin at the first key of the - index. + Positions an index cursor to the index specified in the + handle. Fetches the row if available. If the key value is null, + begin at the first key of the index. */ virtual int index_read_idx_map(uchar * buf, uint index, const uchar * key, key_part_map keypart_map, @@ -1430,6 +1451,79 @@ public: uint key_len= calculate_key_len(table, active_index, key, keypart_map); return index_read_last(buf, key, key_len); } + inline void update_index_statistics() + { + index_rows_read[active_index]++; + rows_read++; + } +public: + + /* Similar functions like the above, but does statistics counting */ + inline int ha_index_read_map(uchar * buf, const uchar * key, + key_part_map keypart_map, + enum ha_rkey_function find_flag) + { + int error= index_read_map(buf, key, keypart_map, find_flag); + if (!error) + update_index_statistics(); + return error; + } + inline int ha_index_read_idx_map(uchar * buf, uint index, const uchar * key, + key_part_map keypart_map, + enum ha_rkey_function find_flag) + { + int error= index_read_idx_map(buf, index, key, keypart_map, find_flag); + if (!error) + { + rows_read++; + index_rows_read[index]++; + } + return error; + } + inline int ha_index_next(uchar * buf) + { + int error= index_next(buf); + if (!error) + update_index_statistics(); + return error; + } + inline int ha_index_prev(uchar * buf) + { + int error= index_prev(buf); + if (!error) + update_index_statistics(); + return error; + } + inline int ha_index_first(uchar * buf) + { + int error= index_first(buf); + if (!error) + update_index_statistics(); + return error; + } + inline int ha_index_last(uchar * buf) + { + int error= index_last(buf); + if (!error) + update_index_statistics(); + return error; + } + inline int ha_index_next_same(uchar *buf, const uchar *key, uint keylen) + { + int error= index_next_same(buf, key, keylen); + if (!error) + update_index_statistics(); + return error; + } + inline int ha_index_read_last_map(uchar * buf, const uchar * key, + key_part_map keypart_map) + { + int error= index_read_last_map(buf, key, keypart_map); + if (!error) + update_index_statistics(); + return error; + } + virtual int read_multi_range_first(KEY_MULTI_RANGE **found_range_p, KEY_MULTI_RANGE *ranges, uint range_count, bool sorted, HANDLER_BUFFER *buffer); @@ -1443,6 +1537,7 @@ public: void ft_end() { ft_handler=NULL; } virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key) { return NULL; } +private: virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; } virtual int rnd_next(uchar *buf)=0; virtual int rnd_pos(uchar * buf, uchar *pos)=0; @@ -1453,11 +1548,50 @@ public: handlers for random position. */ virtual int rnd_pos_by_record(uchar *record) - { - position(record); - return rnd_pos(record, ref); - } + { + position(record); + return rnd_pos(record, ref); + } virtual int read_first_row(uchar *buf, uint primary_key); +public: + + /* Same as above, but with statistics */ + inline int ha_ft_read(uchar *buf) + { + int error= ft_read(buf); + if (!error) + rows_read++; + return error; + } + inline int ha_rnd_next(uchar *buf) + { + int error= rnd_next(buf); + if (!error) + rows_read++; + return error; + } + inline int ha_rnd_pos(uchar *buf, uchar *pos) + { + int error= rnd_pos(buf, pos); + if (!error) + rows_read++; + return error; + } + inline int ha_rnd_pos_by_record(uchar *buf) + { + int error= rnd_pos_by_record(buf); + if (!error) + rows_read++; + return error; + } + inline int ha_read_first_row(uchar *buf, uint primary_key) + { + int error= read_first_row(buf, primary_key); + if (!error) + rows_read++; + return error; + } + /** The following 3 function is only needed for tables that may be internal temporary tables during joins. @@ -1626,6 +1760,9 @@ public: virtual bool is_crashed() const { return 0; } virtual bool auto_repair() const { return 0; } + void update_global_table_stats(); + void update_global_index_stats(); + #define CHF_CREATE_FLAG 0 #define CHF_DELETE_FLAG 1 #define CHF_RENAME_FLAG 2 @@ -1944,6 +2081,7 @@ private: { return HA_ERR_WRONG_COMMAND; } virtual int rename_partitions(const char *path) { return HA_ERR_WRONG_COMMAND; } + friend class ha_partition; }; === modified file 'sql/item_subselect.cc' --- a/sql/item_subselect.cc 2009-09-15 10:46:35 +0000 +++ b/sql/item_subselect.cc 2009-10-19 17:14:48 +0000 @@ -2048,7 +2048,7 @@ int subselect_uniquesubquery_engine::sca table->null_row= 0; for (;;) { - error=table->file->rnd_next(table->record[0]); + error=table->file->ha_rnd_next(table->record[0]); if (error && error != HA_ERR_END_OF_FILE) { error= report_error(table, error); @@ -2222,10 +2222,11 @@ int subselect_uniquesubquery_engine::exe if (!table->file->inited) table->file->ha_index_init(tab->ref.key, 0); - error= table->file->index_read_map(table->record[0], - tab->ref.key_buff, - make_prev_keypart_map(tab->ref.key_parts), - HA_READ_KEY_EXACT); + error= table->file->ha_index_read_map(table->record[0], + tab->ref.key_buff, + make_prev_keypart_map(tab-> + ref.key_parts), + HA_READ_KEY_EXACT); if (error && error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) error= report_error(table, error); @@ -2343,10 +2344,11 @@ int subselect_indexsubquery_engine::exec if (!table->file->inited) table->file->ha_index_init(tab->ref.key, 1); - error= table->file->index_read_map(table->record[0], - tab->ref.key_buff, - make_prev_keypart_map(tab->ref.key_parts), - HA_READ_KEY_EXACT); + error= table->file->ha_index_read_map(table->record[0], + tab->ref.key_buff, + make_prev_keypart_map(tab-> + ref.key_parts), + HA_READ_KEY_EXACT); if (error && error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) error= report_error(table, error); @@ -2367,9 +2369,9 @@ int subselect_indexsubquery_engine::exec ((Item_in_subselect *) item)->value= 1; break; } - error= table->file->index_next_same(table->record[0], - tab->ref.key_buff, - tab->ref.key_length); + error= table->file->ha_index_next_same(table->record[0], + tab->ref.key_buff, + tab->ref.key_length); if (error && error != HA_ERR_END_OF_FILE) { error= report_error(table, error); === modified file 'sql/lex.h' --- a/sql/lex.h 2009-09-07 20:50:10 +0000 +++ b/sql/lex.h 2009-10-19 17:14:48 +0000 @@ -106,6 +106,7 @@ static SYMBOL symbols[] = { { "CHECKSUM", SYM(CHECKSUM_SYM)}, { "CIPHER", SYM(CIPHER_SYM)}, { "CLIENT", SYM(CLIENT_SYM)}, + { "CLIENT_STATISTICS", SYM(CLIENT_STATS_SYM)}, { "CLOSE", SYM(CLOSE_SYM)}, { "COALESCE", SYM(COALESCE)}, { "CODE", SYM(CODE_SYM)}, @@ -245,6 +246,7 @@ static SYMBOL symbols[] = { { "IN", SYM(IN_SYM)}, { "INDEX", SYM(INDEX_SYM)}, { "INDEXES", SYM(INDEXES)}, + { "INDEX_STATISTICS", SYM(INDEX_STATS_SYM)}, { "INFILE", SYM(INFILE)}, { "INITIAL_SIZE", SYM(INITIAL_SIZE_SYM)}, { "INNER", SYM(INNER_SYM)}, @@ -478,6 +480,7 @@ static SYMBOL symbols[] = { { "SIGNED", SYM(SIGNED_SYM)}, { "SIMPLE", SYM(SIMPLE_SYM)}, { "SLAVE", SYM(SLAVE)}, + { "SLOW", SYM(SLOW_SYM)}, { "SNAPSHOT", SYM(SNAPSHOT_SYM)}, { "SMALLINT", SYM(SMALLINT)}, { "SOCKET", SYM(SOCKET_SYM)}, @@ -526,6 +529,7 @@ static SYMBOL symbols[] = { { "TABLE", SYM(TABLE_SYM)}, { "TABLES", SYM(TABLES)}, { "TABLESPACE", SYM(TABLESPACE)}, + { "TABLE_STATISTICS", SYM(TABLE_STATS_SYM)}, { "TABLE_CHECKSUM", SYM(TABLE_CHECKSUM_SYM)}, { "TEMPORARY", SYM(TEMPORARY)}, { "TEMPTABLE", SYM(TEMPTABLE_SYM)}, @@ -569,6 +573,7 @@ static SYMBOL symbols[] = { { "USE", SYM(USE_SYM)}, { "USER", SYM(USER)}, { "USER_RESOURCES", SYM(RESOURCES)}, + { "USER_STATISTICS", SYM(USER_STATS_SYM)}, { "USE_FRM", SYM(USE_FRM)}, { "USING", SYM(USING)}, { "UTC_DATE", SYM(UTC_DATE_SYM)}, === modified file 'sql/log.cc' --- a/sql/log.cc 2009-09-15 10:46:35 +0000 +++ b/sql/log.cc 2009-10-19 17:14:48 +0000 @@ -821,6 +821,13 @@ void Log_to_file_event_handler::flush() mysql_slow_log.reopen_file(); } +void Log_to_file_event_handler::flush_slow_log() +{ + /* reopen slow log file */ + if (opt_slow_log) + mysql_slow_log.reopen_file(); +} + /* Log error with all enabled log event handlers @@ -916,8 +923,6 @@ void LOGGER::init_log_tables() bool LOGGER::flush_logs(THD *thd) { - int rc= 0; - /* Now we lock logger, as nobody should be able to use logging routines while log tables are closed @@ -929,7 +934,24 @@ bool LOGGER::flush_logs(THD *thd) /* end of log flush */ logger.unlock(); - return rc; + return 0; +} + + +bool LOGGER::flush_slow_log(THD *thd) +{ + /* + Now we lock logger, as nobody should be able to use logging routines while + log tables are closed + */ + logger.lock_exclusive(); + + /* reopen log files */ + file_log_handler->flush_slow_log(); + + /* end of log flush */ + logger.unlock(); + return 0; } @@ -4070,6 +4092,7 @@ bool MYSQL_BIN_LOG::write(Log_event *eve if (likely(is_open())) { IO_CACHE *file= &log_file; + my_off_t my_org_b_tell; #ifdef HAVE_REPLICATION /* In the future we need to add to the following if tests like @@ -4077,7 +4100,7 @@ bool MYSQL_BIN_LOG::write(Log_event *eve binlog_[wild_]{do|ignore}_table?" (WL#1049)" */ const char *local_db= event_info->get_db(); - if ((thd && !(thd->options & OPTION_BIN_LOG)) || + if ((!(thd->options & OPTION_BIN_LOG)) || (!binlog_filter->db_ok(local_db))) { VOID(pthread_mutex_unlock(&LOCK_log)); @@ -4085,6 +4108,8 @@ bool MYSQL_BIN_LOG::write(Log_event *eve } #endif /* HAVE_REPLICATION */ + my_org_b_tell= my_b_tell(file); + #if defined(USING_TRANSACTIONS) /* Should we write to the binlog cache or to the binlog on disk? @@ -4095,7 +4120,7 @@ bool MYSQL_BIN_LOG::write(Log_event *eve trans/non-trans table types the best possible in binlogging) - or if the event asks for it (cache_stmt == TRUE). */ - if (opt_using_transactions && thd) + if (opt_using_transactions) { if (thd->binlog_setup_trx_data()) goto err; @@ -4136,7 +4161,6 @@ bool MYSQL_BIN_LOG::write(Log_event *eve If row-based binlogging, Insert_id, Rand and other kind of "setting context" events are not needed. */ - if (thd) { if (!thd->current_stmt_binlog_row_based) { @@ -4183,16 +4207,16 @@ bool MYSQL_BIN_LOG::write(Log_event *eve } } - /* - Write the SQL command - */ - + /* Write the SQL command */ if (event_info->write(file) || DBUG_EVALUATE_IF("injecting_fault_writing", 1, 0)) goto err; if (file == &log_file) // we are writing to the real log (disk) { + ulonglong data_written= (my_b_tell(file) - my_org_b_tell); + status_var_add(thd->status_var.binlog_bytes_written, data_written); + if (flush_and_sync()) goto err; signal_update(); @@ -4318,6 +4342,7 @@ uint MYSQL_BIN_LOG::next_file_id() SYNOPSIS write_cache() + thd Current_thread cache Cache to write to the binary log lock_log True if the LOCK_log mutex should be aquired, false otherwise sync_log True if the log should be flushed and sync:ed @@ -4327,7 +4352,8 @@ uint MYSQL_BIN_LOG::next_file_id() be reset as a READ_CACHE to be able to read the contents from it. */ -int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log) +int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache, bool lock_log, + bool sync_log) { Mutex_sentry sentry(lock_log ? &LOCK_log : NULL); @@ -4375,6 +4401,7 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE /* write the first half of the split header */ if (my_b_write(&log_file, header, carry)) return ER_ERROR_ON_WRITE; + status_var_add(thd->status_var.binlog_bytes_written, carry); /* copy fixed second half of header to cache so the correct @@ -4443,6 +4470,8 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE /* Write data to the binary log file */ if (my_b_write(&log_file, cache->read_pos, length)) return ER_ERROR_ON_WRITE; + status_var_add(thd->status_var.binlog_bytes_written, length); + cache->read_pos=cache->read_end; // Mark buffer used up } while ((length= my_b_fill(cache))); @@ -4494,6 +4523,8 @@ bool MYSQL_BIN_LOG::write_incident(THD * if (lock) pthread_mutex_lock(&LOCK_log); ev.write(&log_file); + status_var_add(thd->status_var.binlog_bytes_written, ev.data_written); + if (lock) { if (!error && !(error= flush_and_sync())) @@ -4565,21 +4596,28 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_C */ if (qinfo.write(&log_file)) goto err; + status_var_add(thd->status_var.binlog_bytes_written, qinfo.data_written); DBUG_EXECUTE_IF("crash_before_writing_xid", { - if ((write_error= write_cache(cache, false, true))) + if ((write_error= write_cache(thd, cache, FALSE, + TRUE))) DBUG_PRINT("info", ("error writing binlog cache: %d", write_error)); DBUG_PRINT("info", ("crashing before writing xid")); abort(); }); - if ((write_error= write_cache(cache, false, false))) + if ((write_error= write_cache(thd, cache, FALSE, FALSE))) goto err; - if (commit_event && commit_event->write(&log_file)) - goto err; + if (commit_event) + { + if (commit_event->write(&log_file)) + goto err; + status_var_add(thd->status_var.binlog_bytes_written, + commit_event->data_written); + } if (incident && write_incident(thd, FALSE)) goto err; === modified file 'sql/log.h' --- a/sql/log.h 2009-06-18 13:52:46 +0000 +++ b/sql/log.h 2009-10-19 17:14:48 +0000 @@ -359,7 +359,8 @@ public: bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident); bool write_incident(THD *thd, bool lock); - int write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync); + int write_cache(THD *thd, IO_CACHE *cache, bool lock_log, + bool flush_and_sync); void set_write_error(THD *thd); bool check_write_error(THD *thd); @@ -487,6 +488,7 @@ public: const char *sql_text, uint sql_text_len, CHARSET_INFO *client_cs); void flush(); + void flush_slow_log(); void init_pthread_objects(); MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; } MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; } @@ -531,6 +533,7 @@ public: void init_base(); void init_log_tables(); bool flush_logs(THD *thd); + bool flush_slow_log(THD *thd); /* Perform basic logger cleanup. this will leave e.g. error log open. */ void cleanup_base(); /* Free memory. Nothing could be logged after this function is called */ === modified file 'sql/log_event.cc' --- a/sql/log_event.cc 2009-09-07 20:50:10 +0000 +++ b/sql/log_event.cc 2009-10-19 17:14:48 +0000 @@ -4465,7 +4465,7 @@ int Load_log_event::do_apply_event(NET* as the present method does not call mysql_parse(). */ lex_start(thd); - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, 0); if (!use_rli_only_for_errors) { @@ -6262,7 +6262,7 @@ int Append_block_log_event::do_apply_eve as the present method does not call mysql_parse(). */ lex_start(thd); - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, 0); my_delete(fname, MYF(0)); // old copy may exist already if ((fd= my_create(fname, CREATE_MODE, O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, @@ -7202,7 +7202,7 @@ int Rows_log_event::do_apply_event(Relay we need to do any changes to that value after this function. */ lex_start(thd); - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, 0); /* The current statement is just about to begin and has not yet modified anything. Note, all.modified is reset @@ -8465,7 +8465,7 @@ Rows_log_event::write_row(const Relay_lo if (table->file->ha_table_flags() & HA_DUPLICATE_POS) { DBUG_PRINT("info",("Locating offending record using rnd_pos()")); - error= table->file->rnd_pos(table->record[1], table->file->dup_ref); + error= table->file->ha_rnd_pos(table->record[1], table->file->dup_ref); if (error) { DBUG_PRINT("info",("rnd_pos() returns error %d",error)); @@ -8497,10 +8497,10 @@ Rows_log_event::write_row(const Relay_lo key_copy((uchar*)key.get(), table->record[0], table->key_info + keynum, 0); - error= table->file->index_read_idx_map(table->record[1], keynum, - (const uchar*)key.get(), - HA_WHOLE_KEY, - HA_READ_KEY_EXACT); + error= table->file->ha_index_read_idx_map(table->record[1], keynum, + (const uchar*)key.get(), + HA_WHOLE_KEY, + HA_READ_KEY_EXACT); if (error) { DBUG_PRINT("info",("index_read_idx() returns %s", HA_ERR(error))); @@ -8768,13 +8768,14 @@ int Rows_log_event::find_row(const Relay length. Something along these lines should work: ADD>>> store_record(table,record[1]); - int error= table->file->rnd_pos(table->record[0], table->file->ref); + int error= table->file->ha_rnd_pos(table->record[0], + table->file->ref); ADD>>> DBUG_ASSERT(memcmp(table->record[1], table->record[0], table->s->reclength) == 0); */ DBUG_PRINT("info",("locating record using primary key (position)")); - int error= table->file->rnd_pos_by_record(table->record[0]); + int error= table->file->ha_rnd_pos_by_record(table->record[0]); if (error) { DBUG_PRINT("info",("rnd_pos returns error %d",error)); @@ -8834,9 +8835,9 @@ int Rows_log_event::find_row(const Relay table->record[0][table->s->null_bytes - 1]|= 256U - (1U << table->s->last_null_bit_pos); - if ((error= table->file->index_read_map(table->record[0], m_key, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT))) + if ((error= table->file->ha_index_read_map(table->record[0], m_key, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT))) { DBUG_PRINT("info",("no record matching the key found in the table")); if (error == HA_ERR_RECORD_DELETED) @@ -8898,7 +8899,7 @@ int Rows_log_event::find_row(const Relay 256U - (1U << table->s->last_null_bit_pos); } - while ((error= table->file->index_next(table->record[0]))) + while ((error= table->file->ha_index_next(table->record[0]))) { /* We just skip records that has already been deleted */ if (error == HA_ERR_RECORD_DELETED) @@ -8934,7 +8935,7 @@ int Rows_log_event::find_row(const Relay do { restart_rnd_next: - error= table->file->rnd_next(table->record[0]); + error= table->file->ha_rnd_next(table->record[0]); DBUG_PRINT("info", ("error: %s", HA_ERR(error))); switch (error) { === modified file 'sql/log_event_old.cc' --- a/sql/log_event_old.cc 2009-05-19 09:28:05 +0000 +++ b/sql/log_event_old.cc 2009-10-19 17:14:48 +0000 @@ -63,7 +63,7 @@ Old_rows_log_event::do_apply_event(Old_r we need to do any changes to that value after this function. */ lex_start(thd); - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, 0); /* Check if the slave is set to use SBR. If so, it should switch @@ -553,7 +553,7 @@ replace_record(THD *thd, TABLE *table, */ if (table->file->ha_table_flags() & HA_DUPLICATE_POS) { - error= table->file->rnd_pos(table->record[1], table->file->dup_ref); + error= table->file->ha_rnd_pos(table->record[1], table->file->dup_ref); if (error) { DBUG_PRINT("info",("rnd_pos() returns error %d",error)); @@ -579,10 +579,10 @@ replace_record(THD *thd, TABLE *table, key_copy((uchar*)key.get(), table->record[0], table->key_info + keynum, 0); - error= table->file->index_read_idx_map(table->record[1], keynum, - (const uchar*)key.get(), - HA_WHOLE_KEY, - HA_READ_KEY_EXACT); + error= table->file->ha_index_read_idx_map(table->record[1], keynum, + (const uchar*)key.get(), + HA_WHOLE_KEY, + HA_READ_KEY_EXACT); if (error) { DBUG_PRINT("info", ("index_read_idx() returns error %d", error)); @@ -694,13 +694,13 @@ static int find_and_fetch_row(TABLE *tab length. Something along these lines should work: ADD>>> store_record(table,record[1]); - int error= table->file->rnd_pos(table->record[0], table->file->ref); + int error= table->file->ha_rnd_pos(table->record[0], table->file->ref); ADD>>> DBUG_ASSERT(memcmp(table->record[1], table->record[0], table->s->reclength) == 0); */ table->file->position(table->record[0]); - int error= table->file->rnd_pos(table->record[0], table->file->ref); + int error= table->file->ha_rnd_pos(table->record[0], table->file->ref); /* rnd_pos() returns the record in table->record[0], so we have to move it to table->record[1]. @@ -738,8 +738,9 @@ static int find_and_fetch_row(TABLE *tab my_ptrdiff_t const pos= table->s->null_bytes > 0 ? table->s->null_bytes - 1 : 0; table->record[1][pos]= 0xFF; - if ((error= table->file->index_read_map(table->record[1], key, HA_WHOLE_KEY, - HA_READ_KEY_EXACT))) + if ((error= table->file->ha_index_read_map(table->record[1], key, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT))) { table->file->print_error(error, MYF(0)); table->file->ha_index_end(); @@ -793,7 +794,7 @@ static int find_and_fetch_row(TABLE *tab 256U - (1U << table->s->last_null_bit_pos); } - while ((error= table->file->index_next(table->record[1]))) + while ((error= table->file->ha_index_next(table->record[1]))) { /* We just skip records that has already been deleted */ if (error == HA_ERR_RECORD_DELETED) @@ -822,7 +823,7 @@ static int find_and_fetch_row(TABLE *tab do { restart_rnd_next: - error= table->file->rnd_next(table->record[1]); + error= table->file->ha_rnd_next(table->record[1]); DBUG_DUMP("record[0]", table->record[0], table->s->reclength); DBUG_DUMP("record[1]", table->record[1], table->s->reclength); @@ -2115,7 +2116,7 @@ Old_rows_log_event::write_row(const Rela if (table->file->ha_table_flags() & HA_DUPLICATE_POS) { DBUG_PRINT("info",("Locating offending record using rnd_pos()")); - error= table->file->rnd_pos(table->record[1], table->file->dup_ref); + error= table->file->ha_rnd_pos(table->record[1], table->file->dup_ref); if (error) { DBUG_PRINT("info",("rnd_pos() returns error %d",error)); @@ -2147,10 +2148,10 @@ Old_rows_log_event::write_row(const Rela key_copy((uchar*)key.get(), table->record[0], table->key_info + keynum, 0); - error= table->file->index_read_idx_map(table->record[1], keynum, - (const uchar*)key.get(), - HA_WHOLE_KEY, - HA_READ_KEY_EXACT); + error= table->file->ha_index_read_idx_map(table->record[1], keynum, + (const uchar*)key.get(), + HA_WHOLE_KEY, + HA_READ_KEY_EXACT); if (error) { DBUG_PRINT("info",("index_read_idx() returns error %d", error)); @@ -2301,13 +2302,13 @@ int Old_rows_log_event::find_row(const R length. Something along these lines should work: ADD>>> store_record(table,record[1]); - int error= table->file->rnd_pos(table->record[0], table->file->ref); + int error= table->file->ha_rnd_pos(table->record[0], table->file->ref); ADD>>> DBUG_ASSERT(memcmp(table->record[1], table->record[0], table->s->reclength) == 0); */ DBUG_PRINT("info",("locating record using primary key (position)")); - int error= table->file->rnd_pos_by_record(table->record[0]); + int error= table->file->ha_rnd_pos_by_record(table->record[0]); if (error) { DBUG_PRINT("info",("rnd_pos returns error %d",error)); @@ -2367,9 +2368,9 @@ int Old_rows_log_event::find_row(const R table->s->null_bytes > 0 ? table->s->null_bytes - 1 : 0; table->record[0][pos]= 0xFF; - if ((error= table->file->index_read_map(table->record[0], m_key, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT))) + if ((error= table->file->ha_index_read_map(table->record[0], m_key, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT))) { DBUG_PRINT("info",("no record matching the key found in the table")); if (error == HA_ERR_RECORD_DELETED) @@ -2431,7 +2432,7 @@ int Old_rows_log_event::find_row(const R 256U - (1U << table->s->last_null_bit_pos); } - while ((error= table->file->index_next(table->record[0]))) + while ((error= table->file->ha_index_next(table->record[0]))) { /* We just skip records that has already been deleted */ if (error == HA_ERR_RECORD_DELETED) @@ -2467,7 +2468,7 @@ int Old_rows_log_event::find_row(const R do { restart_rnd_next: - error= table->file->rnd_next(table->record[0]); + error= table->file->ha_rnd_next(table->record[0]); switch (error) { === modified file 'sql/mysql_priv.h' --- a/sql/mysql_priv.h 2009-10-06 14:53:46 +0000 +++ b/sql/mysql_priv.h 2009-10-19 17:14:48 +0000 @@ -1063,6 +1063,7 @@ bool setup_connection_thread_globals(THD bool login_connection(THD *thd); void end_connection(THD *thd); void prepare_new_connection_state(THD* thd); +void update_global_user_stats(THD* thd, bool create_user, time_t now); int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create); @@ -1099,14 +1100,22 @@ bool is_update_query(enum enum_sql_comma bool is_log_table_write_query(enum enum_sql_command command); bool alloc_query(THD *thd, const char *packet, uint packet_length); void mysql_init_select(LEX *lex); -void mysql_reset_thd_for_next_command(THD *thd); +void mysql_reset_thd_for_next_command(THD *thd, my_bool calculate_userstat); bool mysql_new_select(LEX *lex, bool move_down); void create_select_for_variable(const char *var_name); void mysql_init_multi_delete(LEX *lex); bool multi_delete_set_locks_and_link_aux_tables(LEX *lex); void init_max_user_conn(void); void init_update_queries(void); +void init_global_user_stats(void); +void init_global_table_stats(void); +void init_global_index_stats(void); +void init_global_client_stats(void); void free_max_user_conn(void); +void free_global_user_stats(void); +void free_global_table_stats(void); +void free_global_index_stats(void); +void free_global_client_stats(void); pthread_handler_t handle_bootstrap(void *arg); int mysql_execute_command(THD *thd); bool do_command(THD *thd); @@ -1967,6 +1976,7 @@ extern ulong max_connect_errors, connect extern ulong extra_max_connections; extern ulong slave_net_timeout, slave_trans_retries; extern uint max_user_connections; +extern ulonglong denied_connections; extern ulong what_to_log,flush_time; extern ulong query_buff_size; extern ulong max_prepared_stmt_count, prepared_stmt_count; @@ -2020,6 +2030,7 @@ extern my_bool opt_safe_show_db, opt_loc extern my_bool opt_slave_compressed_protocol, use_temp_pool; extern ulong slave_exec_mode_options; extern my_bool opt_readonly, lower_case_file_system; +extern my_bool opt_userstat_running; extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs; extern my_bool opt_secure_auth; extern char* opt_secure_file_priv; @@ -2060,6 +2071,11 @@ extern pthread_mutex_t LOCK_des_key_file #endif extern pthread_mutex_t LOCK_server_started; extern pthread_cond_t COND_server_started; +extern pthread_mutex_t LOCK_global_user_client_stats; +extern pthread_mutex_t LOCK_global_table_stats; +extern pthread_mutex_t LOCK_global_index_stats; +extern pthread_mutex_t LOCK_stats; + extern int mysqld_server_started; extern rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; extern rw_lock_t LOCK_system_variables_hash; @@ -2086,6 +2102,11 @@ extern KNOWN_DATE_TIME_FORMAT known_date extern String null_string; extern HASH open_cache, lock_db_cache; +extern HASH global_user_stats; +extern HASH global_client_stats; +extern HASH global_table_stats; +extern HASH global_index_stats; + extern TABLE *unused_tables; extern const char* any_db; extern struct my_option my_long_options[]; === modified file 'sql/mysqld.cc' --- a/sql/mysqld.cc 2009-10-07 13:07:10 +0000 +++ b/sql/mysqld.cc 2009-10-19 17:14:48 +0000 @@ -416,6 +416,7 @@ static pthread_cond_t COND_thread_cache, bool opt_update_log, opt_bin_log, opt_ignore_builtin_innodb= 0; my_bool opt_log, opt_slow_log; +my_bool opt_userstat_running; ulong log_output_options; my_bool opt_log_queries_not_using_indexes= 0; bool opt_error_log= IF_WIN(1,0); @@ -548,6 +549,7 @@ ulong binlog_cache_use= 0, binlog_cache_ ulong max_connections, max_connect_errors; ulong extra_max_connections; uint max_user_connections= 0; +ulonglong denied_connections; /** Limit of the total number of prepared statements in the server. Is necessary to protect the server against out-of-memory attacks. @@ -649,6 +651,9 @@ pthread_mutex_t LOCK_mysql_create_db, LO LOCK_global_system_variables, LOCK_user_conn, LOCK_slave_list, LOCK_active_mi, LOCK_connection_count, LOCK_uuid_generator; +pthread_mutex_t LOCK_stats, LOCK_global_user_client_stats; +pthread_mutex_t LOCK_global_table_stats, LOCK_global_index_stats; + /** The below lock protects access to two global server variables: max_prepared_stmt_count and prepared_stmt_count. These variables @@ -1342,6 +1347,10 @@ void clean_up(bool print_message) x_free(opt_secure_file_priv); bitmap_free(&temp_pool); free_max_user_conn(); + free_global_user_stats(); + free_global_client_stats(); + free_global_table_stats(); + free_global_index_stats(); #ifdef HAVE_REPLICATION end_slave_list(); #endif @@ -1428,6 +1437,11 @@ static void clean_up_mutexes() (void) pthread_mutex_destroy(&LOCK_bytes_received); (void) pthread_mutex_destroy(&LOCK_user_conn); (void) pthread_mutex_destroy(&LOCK_connection_count); + (void) pthread_mutex_destroy(&LOCK_stats); + (void) pthread_mutex_destroy(&LOCK_global_user_client_stats); + (void) pthread_mutex_destroy(&LOCK_global_table_stats); + (void) pthread_mutex_destroy(&LOCK_global_index_stats); + Events::destroy_mutexes(); #ifdef HAVE_OPENSSL (void) pthread_mutex_destroy(&LOCK_des_key_file); @@ -3203,6 +3217,7 @@ SHOW_VAR com_status_vars[]= { {"show_binlog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS}, {"show_binlogs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS}, {"show_charsets", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS}, + {"show_client_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CLIENT_STATS]), SHOW_LONG_STATUS}, {"show_collations", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS}, {"show_column_types", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLUMN_TYPES]), SHOW_LONG_STATUS}, {"show_contributors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CONTRIBUTORS]), SHOW_LONG_STATUS}, @@ -3225,6 +3240,7 @@ SHOW_VAR com_status_vars[]= { {"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS}, {"show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS}, {"show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS}, + {"show_index_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_INDEX_STATS]), SHOW_LONG_STATUS}, {"show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS}, {"show_new_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS}, {"show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS}, @@ -3241,9 +3257,11 @@ SHOW_VAR com_status_vars[]= { {"show_slave_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS}, {"show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS}, {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS}, + {"show_table_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATS]), SHOW_LONG_STATUS}, {"show_table_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS}, {"show_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS}, {"show_triggers", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS}, + {"show_user_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_USER_STATS]), SHOW_LONG_STATUS}, {"show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS}, {"show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS}, {"slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS}, @@ -3642,6 +3660,12 @@ static int init_thread_environment() (void) pthread_mutex_init(&LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_connection_count, MY_MUTEX_INIT_FAST); + (void) pthread_mutex_init(&LOCK_stats, MY_MUTEX_INIT_FAST); + (void) pthread_mutex_init(&LOCK_global_user_client_stats, + MY_MUTEX_INIT_FAST); + (void) pthread_mutex_init(&LOCK_global_table_stats, MY_MUTEX_INIT_FAST); + (void) pthread_mutex_init(&LOCK_global_index_stats, MY_MUTEX_INIT_FAST); + #ifdef HAVE_OPENSSL (void) pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST); #ifndef HAVE_YASSL @@ -4005,6 +4029,9 @@ server."); /* call ha_init_key_cache() on all key caches to init them */ process_key_caches(&ha_init_key_cache); + init_global_table_stats(); + init_global_index_stats(); + /* Allow storage engine to give real error messages */ if (ha_init_errors()) DBUG_RETURN(1); @@ -4210,6 +4237,8 @@ server."); init_max_user_conn(); init_update_queries(); + init_global_user_stats(); + init_global_client_stats(); DBUG_RETURN(0); } @@ -5019,6 +5048,7 @@ static void create_new_thread(THD *thd) DBUG_PRINT("error",("Too many connections")); close_connection(thd, ER_CON_COUNT_ERROR, 1); + statistic_increment(denied_connections, &LOCK_status); delete thd; DBUG_VOID_RETURN; } @@ -5810,6 +5840,7 @@ enum options_mysqld OPT_LOG_SLOW_RATE_LIMIT, OPT_LOG_SLOW_VERBOSITY, OPT_LOG_SLOW_FILTER, + OPT_USERSTAT, OPT_GENERAL_LOG_FILE, OPT_SLOW_QUERY_LOG_FILE, OPT_IGNORE_BUILTIN_INNODB @@ -7209,6 +7240,10 @@ The minimum value for this variable is 4 (uchar**) &max_system_variables.net_wait_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT), 0, 1, 0}, + {"userstat", OPT_USERSTAT, + "Control USER_STATISTICS, CLIENT_STATISTICS, INDEX_STATISTICS and TABLE_STATISTICS running", + (uchar**) &opt_userstat_running, (uchar**) &opt_userstat_running, + 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -7579,19 +7614,24 @@ static int show_ssl_get_cipher_list(THD SHOW_VAR status_vars[]= { {"Aborted_clients", (char*) &aborted_threads, SHOW_LONG}, {"Aborted_connects", (char*) &aborted_connects, SHOW_LONG}, + {"Access_denied_errors", (char*) offsetof(STATUS_VAR, access_denied_errors), SHOW_LONG_STATUS}, {"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG}, {"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG}, + {"Busy_time", (char*) offsetof(STATUS_VAR, busy_time), SHOW_DOUBLE_STATUS}, {"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS}, {"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS}, + {"Binlog_bytes_written", (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS}, {"Com", (char*) com_status_vars, SHOW_ARRAY}, {"Compression", (char*) &show_net_compression, SHOW_FUNC}, {"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH}, + {"Cpu_time", (char*) offsetof(STATUS_VAR, cpu_time), SHOW_DOUBLE_STATUS}, {"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS}, {"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG}, {"Created_tmp_tables", (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS}, {"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG}, {"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH}, {"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG}, + {"Empty_queries", (char*) offsetof(STATUS_VAR, empty_queries), SHOW_LONG_STATUS}, {"Flush_commands", (char*) &refresh_version, SHOW_LONG_NOFLUSH}, {"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS}, {"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS}, @@ -7626,6 +7666,8 @@ SHOW_VAR status_vars[]= { {"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS}, {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS}, {"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_FUNC}, + {"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONG_STATUS}, + {"Rows_read", (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONG_STATUS}, #ifdef HAVE_QUERY_CACHE {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH}, {"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH}, @@ -9110,6 +9152,8 @@ void refresh_status(THD *thd) /* Reset thread's status variables */ bzero((uchar*) &thd->status_var, sizeof(thd->status_var)); + bzero((uchar*) &thd->org_status_var, sizeof(thd->org_status_var)); + thd->start_bytes_received= 0; /* Reset some global variables */ reset_status_vars(); === modified file 'sql/opt_range.cc' --- a/sql/opt_range.cc 2009-09-09 21:59:28 +0000 +++ b/sql/opt_range.cc 2009-10-19 17:14:48 +0000 @@ -8230,7 +8230,7 @@ int QUICK_ROR_INTERSECT_SELECT::get_next /* We get here if we got the same row ref in all scans. */ if (need_to_fetch_row) - error= head->file->rnd_pos(head->record[0], last_rowid); + error= head->file->ha_rnd_pos(head->record[0], last_rowid); } while (error == HA_ERR_RECORD_DELETED); DBUG_RETURN(error); } @@ -8296,7 +8296,7 @@ int QUICK_ROR_UNION_SELECT::get_next() cur_rowid= prev_rowid; prev_rowid= tmp; - error= head->file->rnd_pos(quick->record, prev_rowid); + error= head->file->ha_rnd_pos(quick->record, prev_rowid); } while (error == HA_ERR_RECORD_DELETED); DBUG_RETURN(error); } @@ -8521,10 +8521,12 @@ int QUICK_RANGE_SELECT::get_next_prefix( key_range start_key, end_key; if (last_range) { - /* Read the next record in the same range with prefix after cur_prefix. */ + /* + Read the next record in the same range with prefix after cur_prefix. + */ DBUG_ASSERT(cur_prefix != 0); - result= file->index_read_map(record, cur_prefix, keypart_map, - HA_READ_AFTER_KEY); + result= file->ha_index_read_map(record, cur_prefix, keypart_map, + HA_READ_AFTER_KEY); if (result || (file->compare_key(file->end_range) <= 0)) DBUG_RETURN(result); } @@ -8580,8 +8582,8 @@ int QUICK_RANGE_SELECT_GEOM::get_next() if (last_range) { // Already read through key - result= file->index_next_same(record, last_range->min_key, - last_range->min_length); + result= file->ha_index_next_same(record, last_range->min_key, + last_range->min_length); if (result != HA_ERR_END_OF_FILE) DBUG_RETURN(result); } @@ -8595,10 +8597,10 @@ int QUICK_RANGE_SELECT_GEOM::get_next() } last_range= *(cur_range++); - result= file->index_read_map(record, last_range->min_key, - last_range->min_keypart_map, - (ha_rkey_function)(last_range->flag ^ - GEOM_FLAG)); + result= file->ha_index_read_map(record, last_range->min_key, + last_range->min_keypart_map, + (ha_rkey_function)(last_range->flag ^ + GEOM_FLAG)); if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE) DBUG_RETURN(result); last_range= 0; // Not found, to next range @@ -8710,9 +8712,9 @@ int QUICK_SELECT_DESC::get_next() { // Already read through key result = ((last_range->flag & EQ_RANGE && used_key_parts <= head->key_info[index].key_parts) ? - file->index_next_same(record, last_range->min_key, + file->ha_index_next_same(record, last_range->min_key, last_range->min_length) : - file->index_prev(record)); + file->ha_index_prev(record)); if (!result) { if (cmp_prev(*rev_it.ref()) == 0) @@ -8728,7 +8730,7 @@ int QUICK_SELECT_DESC::get_next() if (last_range->flag & NO_MAX_RANGE) // Read last record { int local_error; - if ((local_error=file->index_last(record))) + if ((local_error= file->ha_index_last(record))) DBUG_RETURN(local_error); // Empty table if (cmp_prev(last_range) == 0) DBUG_RETURN(0); @@ -8740,9 +8742,9 @@ int QUICK_SELECT_DESC::get_next() used_key_parts <= head->key_info[index].key_parts) { - result = file->index_read_map(record, last_range->max_key, - last_range->max_keypart_map, - HA_READ_KEY_EXACT); + result= file->ha_index_read_map(record, last_range->max_key, + last_range->max_keypart_map, + HA_READ_KEY_EXACT); } else { @@ -8750,11 +8752,11 @@ int QUICK_SELECT_DESC::get_next() (last_range->flag & EQ_RANGE && used_key_parts > head->key_info[index].key_parts) || range_reads_after_key(last_range)); - result=file->index_read_map(record, last_range->max_key, - last_range->max_keypart_map, - ((last_range->flag & NEAR_MAX) ? - HA_READ_BEFORE_KEY : - HA_READ_PREFIX_LAST_OR_PREV)); + result= file->ha_index_read_map(record, last_range->max_key, + last_range->max_keypart_map, + ((last_range->flag & NEAR_MAX) ? + HA_READ_BEFORE_KEY : + HA_READ_PREFIX_LAST_OR_PREV)); } if (result) { @@ -10467,7 +10469,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::reset(vo DBUG_RETURN(result); if (quick_prefix_select && quick_prefix_select->reset()) DBUG_RETURN(1); - result= file->index_last(record); + result= file->ha_index_last(record); if (result == HA_ERR_END_OF_FILE) DBUG_RETURN(0); /* Save the prefix of the last group. */ @@ -10569,9 +10571,9 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next first sub-group with the extended prefix. */ if (!have_min && !have_max && key_infix_len > 0) - result= file->index_read_map(record, group_prefix, - make_prev_keypart_map(real_key_parts), - HA_READ_KEY_EXACT); + result= file->ha_index_read_map(record, group_prefix, + make_prev_keypart_map(real_key_parts), + HA_READ_KEY_EXACT); result= have_min ? min_res : have_max ? max_res : result; } while ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) && @@ -10633,9 +10635,10 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min /* Apply the constant equality conditions to the non-group select fields */ if (key_infix_len > 0) { - if ((result= file->index_read_map(record, group_prefix, - make_prev_keypart_map(real_key_parts), - HA_READ_KEY_EXACT))) + if ((result= + file->ha_index_read_map(record, group_prefix, + make_prev_keypart_map(real_key_parts), + HA_READ_KEY_EXACT))) DBUG_RETURN(result); } @@ -10650,9 +10653,9 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min { /* Find the first subsequent record without NULL in the MIN/MAX field. */ key_copy(tmp_record, record, index_info, 0); - result= file->index_read_map(record, tmp_record, - make_keypart_map(real_key_parts), - HA_READ_AFTER_KEY); + result= file->ha_index_read_map(record, tmp_record, + make_keypart_map(real_key_parts), + HA_READ_AFTER_KEY); /* Check if the new record belongs to the current group by comparing its prefix with the group's prefix. If it is from the next group, then the @@ -10707,9 +10710,9 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max if (min_max_ranges.elements > 0) result= next_max_in_range(); else - result= file->index_read_map(record, group_prefix, - make_prev_keypart_map(real_key_parts), - HA_READ_PREFIX_LAST); + result= file->ha_index_read_map(record, group_prefix, + make_prev_keypart_map(real_key_parts), + HA_READ_PREFIX_LAST); DBUG_RETURN(result); } @@ -10752,7 +10755,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_pre { if (!seen_first_key) { - result= file->index_first(record); + result= file->ha_index_first(record); if (result) DBUG_RETURN(result); seen_first_key= TRUE; @@ -10760,9 +10763,9 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_pre else { /* Load the first key in this group into record. */ - result= file->index_read_map(record, group_prefix, - make_prev_keypart_map(group_key_parts), - HA_READ_AFTER_KEY); + result= file->ha_index_read_map(record, group_prefix, + make_prev_keypart_map(group_key_parts), + HA_READ_AFTER_KEY); if (result) DBUG_RETURN(result); } @@ -10839,7 +10842,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min HA_READ_AFTER_KEY : HA_READ_KEY_OR_NEXT; } - result= file->index_read_map(record, group_prefix, keypart_map, find_flag); + result= file->ha_index_read_map(record, group_prefix, keypart_map, + find_flag); if (result) { if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) && @@ -10978,7 +10982,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV; } - result= file->index_read_map(record, group_prefix, keypart_map, find_flag); + result= file->ha_index_read_map(record, group_prefix, keypart_map, + find_flag); if (result) { === modified file 'sql/opt_range.h' --- a/sql/opt_range.h 2009-09-02 08:40:18 +0000 +++ b/sql/opt_range.h 2009-10-19 17:14:48 +0000 @@ -727,7 +727,7 @@ public: ~FT_SELECT() { file->ft_end(); } int init() { return error=file->ft_init(); } int reset() { return 0; } - int get_next() { return error=file->ft_read(record); } + int get_next() { return error= file->ha_ft_read(record); } int get_type() { return QS_TYPE_FULLTEXT; } }; === modified file 'sql/opt_sum.cc' --- a/sql/opt_sum.cc 2009-09-07 20:50:10 +0000 +++ b/sql/opt_sum.cc 2009-10-19 17:14:48 +0000 @@ -254,7 +254,7 @@ int opt_sum_query(TABLE_LIST *tables, Li error= table->file->ha_index_init((uint) ref.key, 1); if (!ref.key_length) - error= table->file->index_first(table->record[0]); + error= table->file->ha_index_first(table->record[0]); else { /* @@ -276,10 +276,10 @@ int opt_sum_query(TABLE_LIST *tables, Li Closed interval: Either The MIN argument is non-nullable, or we have a >= predicate for the MIN argument. */ - error= table->file->index_read_map(table->record[0], - ref.key_buff, - make_prev_keypart_map(ref.key_parts), - HA_READ_KEY_OR_NEXT); + error= table->file->ha_index_read_map(table->record[0], + ref.key_buff, + make_prev_keypart_map(ref.key_parts), + HA_READ_KEY_OR_NEXT); else { /* @@ -288,10 +288,10 @@ int opt_sum_query(TABLE_LIST *tables, Li 2) there is a > predicate on it, nullability is irrelevant. We need to scan the next bigger record first. */ - error= table->file->index_read_map(table->record[0], - ref.key_buff, - make_prev_keypart_map(ref.key_parts), - HA_READ_AFTER_KEY); + error= table->file->ha_index_read_map(table->record[0], + ref.key_buff, + make_prev_keypart_map(ref.key_parts), + HA_READ_AFTER_KEY); /* If the found record is outside the group formed by the search prefix, or there is no such record at all, check if all @@ -314,10 +314,10 @@ int opt_sum_query(TABLE_LIST *tables, Li key_cmp_if_same(table, ref.key_buff, ref.key, prefix_len))) { DBUG_ASSERT(item_field->field->real_maybe_null()); - error= table->file->index_read_map(table->record[0], - ref.key_buff, - make_prev_keypart_map(ref.key_parts), - HA_READ_KEY_EXACT); + error= table->file->ha_index_read_map(table->record[0], + ref.key_buff, + make_prev_keypart_map(ref.key_parts), + HA_READ_KEY_EXACT); } } } @@ -402,13 +402,13 @@ int opt_sum_query(TABLE_LIST *tables, Li error= table->file->ha_index_init((uint) ref.key, 1); if (!ref.key_length) - error= table->file->index_last(table->record[0]); + error= table->file->ha_index_last(table->record[0]); else - error= table->file->index_read_map(table->record[0], key_buff, - make_prev_keypart_map(ref.key_parts), - range_fl & NEAR_MAX ? - HA_READ_BEFORE_KEY : - HA_READ_PREFIX_LAST_OR_PREV); + error= table->file->ha_index_read_map(table->record[0], key_buff, + make_prev_keypart_map(ref.key_parts), + range_fl & NEAR_MAX ? + HA_READ_BEFORE_KEY : + HA_READ_PREFIX_LAST_OR_PREV); if (!error && reckey_in_range(1, &ref, item_field->field, conds, range_fl, prefix_len)) error= HA_ERR_KEY_NOT_FOUND; === modified file 'sql/records.cc' --- a/sql/records.cc 2009-05-06 12:03:24 +0000 +++ b/sql/records.cc 2009-10-19 17:14:48 +0000 @@ -342,7 +342,7 @@ static int rr_quick(READ_RECORD *info) static int rr_index_first(READ_RECORD *info) { - int tmp= info->file->index_first(info->record); + int tmp= info->file->ha_index_first(info->record); info->read_record= rr_index; if (tmp) tmp= rr_handle_error(info, tmp); @@ -368,7 +368,7 @@ static int rr_index_first(READ_RECORD *i static int rr_index(READ_RECORD *info) { - int tmp= info->file->index_next(info->record); + int tmp= info->file->ha_index_next(info->record); if (tmp) tmp= rr_handle_error(info, tmp); return tmp; @@ -378,7 +378,7 @@ static int rr_index(READ_RECORD *info) int rr_sequential(READ_RECORD *info) { int tmp; - while ((tmp=info->file->rnd_next(info->record))) + while ((tmp= info->file->ha_rnd_next(info->record))) { if (info->thd->killed) { @@ -406,7 +406,7 @@ static int rr_from_tempfile(READ_RECORD { if (my_b_read(info->io_cache,info->ref_pos,info->ref_length)) return -1; /* End of file */ - if (!(tmp=info->file->rnd_pos(info->record,info->ref_pos))) + if (!(tmp= info->file->ha_rnd_pos(info->record,info->ref_pos))) break; /* The following is extremely unlikely to happen */ if (tmp == HA_ERR_RECORD_DELETED || @@ -457,7 +457,7 @@ static int rr_from_pointers(READ_RECORD cache_pos= info->cache_pos; info->cache_pos+= info->ref_length; - if (!(tmp=info->file->rnd_pos(info->record,cache_pos))) + if (!(tmp= info->file->ha_rnd_pos(info->record,cache_pos))) break; /* The following is extremely unlikely to happen */ @@ -590,7 +590,7 @@ static int rr_from_cache(READ_RECORD *in record=uint3korr(position); position+=3; record_pos=info->cache+record*info->reclength; - if ((error=(int16) info->file->rnd_pos(record_pos,info->ref_pos))) + if ((error=(int16) info->file->ha_rnd_pos(record_pos,info->ref_pos))) { record_pos[info->error_offset]=1; shortstore(record_pos,error); === modified file 'sql/set_var.cc' --- a/sql/set_var.cc 2009-09-15 10:46:35 +0000 +++ b/sql/set_var.cc 2009-10-19 17:14:48 +0000 @@ -511,6 +511,9 @@ static sys_var_const sys_prot static sys_var_thd_ulong sys_read_buff_size(&vars, "read_buffer_size", &SV::read_buff_size); static sys_var_opt_readonly sys_readonly(&vars, "read_only", &opt_readonly); +static sys_var_bool_ptr sys_userstat(&vars, "userstat", + &opt_userstat_running); + static sys_var_thd_ulong sys_read_rnd_buff_size(&vars, "read_rnd_buffer_size", &SV::read_rnd_buff_size); static sys_var_thd_ulong sys_div_precincrement(&vars, "div_precision_increment", === modified file 'sql/sp.cc' --- a/sql/sp.cc 2009-07-28 22:39:58 +0000 +++ b/sql/sp.cc 2009-10-19 17:14:48 +0000 @@ -344,8 +344,9 @@ db_find_routine_aux(THD *thd, int type, key_copy(key, table->record[0], table->key_info, table->key_info->key_length); - if (table->file->index_read_idx_map(table->record[0], 0, key, HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + if (table->file->ha_index_read_idx_map(table->record[0], 0, key, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) DBUG_RETURN(SP_KEY_NOT_FOUND); DBUG_RETURN(SP_OK); @@ -1101,9 +1102,9 @@ sp_drop_db_routines(THD *thd, char *db) ret= SP_OK; table->file->ha_index_init(0, 1); - if (! table->file->index_read_map(table->record[0], - (uchar *)table->field[MYSQL_PROC_FIELD_DB]->ptr, - (key_part_map)1, HA_READ_KEY_EXACT)) + if (!table->file->ha_index_read_map(table->record[0], + (uchar *) table->field[MYSQL_PROC_FIELD_DB]->ptr, + (key_part_map)1, HA_READ_KEY_EXACT)) { int nxtres; bool deleted= FALSE; @@ -1118,9 +1119,11 @@ sp_drop_db_routines(THD *thd, char *db) nxtres= 0; break; } - } while (! (nxtres= table->file->index_next_same(table->record[0], - (uchar *)table->field[MYSQL_PROC_FIELD_DB]->ptr, - key_len))); + } while (!(nxtres= table->file-> + ha_index_next_same(table->record[0], + (uchar *)table->field[MYSQL_PROC_FIELD_DB]-> + ptr, + key_len))); if (nxtres != HA_ERR_END_OF_FILE) ret= SP_KEY_NOT_FOUND; if (deleted) === modified file 'sql/sql_acl.cc' --- a/sql/sql_acl.cc 2009-09-07 20:50:10 +0000 +++ b/sql/sql_acl.cc 2009-10-19 17:14:48 +0000 @@ -1834,9 +1834,9 @@ static bool update_user_table(THD *thd, key_copy((uchar *) user_key, table->record[0], table->key_info, table->key_info->key_length); - if (table->file->index_read_idx_map(table->record[0], 0, - (uchar *) user_key, HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + if (table->file->ha_index_read_idx_map(table->record[0], 0, + (uchar *) user_key, HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) { my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0)); /* purecov: deadcode */ @@ -1927,9 +1927,9 @@ static int replace_user_table(THD *thd, key_copy(user_key, table->record[0], table->key_info, table->key_info->key_length); - if (table->file->index_read_idx_map(table->record[0], 0, user_key, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + if (table->file->ha_index_read_idx_map(table->record[0], 0, user_key, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) { /* what == 'N' means revoke */ if (what == 'N') @@ -2151,9 +2151,9 @@ static int replace_db_table(TABLE *table key_copy(user_key, table->record[0], table->key_info, table->key_info->key_length); - if (table->file->index_read_idx_map(table->record[0],0, user_key, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + if (table->file->ha_index_read_idx_map(table->record[0],0, user_key, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) { if (what == 'N') { // no row, no revoke @@ -2369,8 +2369,9 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TA col_privs->field[4]->store("",0, &my_charset_latin1); col_privs->file->ha_index_init(0, 1); - if (col_privs->file->index_read_map(col_privs->record[0], (uchar*) key, - (key_part_map)15, HA_READ_KEY_EXACT)) + if (col_privs->file->ha_index_read_map(col_privs->record[0], (uchar*) key, + (key_part_map)15, + HA_READ_KEY_EXACT)) { cols = 0; /* purecov: deadcode */ col_privs->file->ha_index_end(); @@ -2391,7 +2392,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TA return; /* purecov: deadcode */ } my_hash_insert(&hash_columns, (uchar *) mem_check); - } while (!col_privs->file->index_next(col_privs->record[0]) && + } while (!col_privs->file->ha_index_next(col_privs->record[0]) && !key_cmp_if_same(col_privs,key,0,key_prefix_len)); col_privs->file->ha_index_end(); } @@ -2532,8 +2533,8 @@ static int replace_column_table(GRANT_TA key_copy(user_key, table->record[0], table->key_info, table->key_info->key_length); - if (table->file->index_read_map(table->record[0], user_key, HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + if (table->file->ha_index_read_map(table->record[0], user_key, + HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { if (revoke_grant) { @@ -2610,9 +2611,9 @@ static int replace_column_table(GRANT_TA key_copy(user_key, table->record[0], table->key_info, key_prefix_length); - if (table->file->index_read_map(table->record[0], user_key, - (key_part_map)15, - HA_READ_KEY_EXACT)) + if (table->file->ha_index_read_map(table->record[0], user_key, + (key_part_map)15, + HA_READ_KEY_EXACT)) goto end; /* Scan through all rows with the same host,db,user and table */ @@ -2663,7 +2664,7 @@ static int replace_column_table(GRANT_TA hash_delete(&g_t->hash_columns,(uchar*) grant_column); } } - } while (!table->file->index_next(table->record[0]) && + } while (!table->file->ha_index_next(table->record[0]) && !key_cmp_if_same(table, key, 0, key_prefix_length)); } @@ -2713,9 +2714,9 @@ static int replace_table_table(THD *thd, key_copy(user_key, table->record[0], table->key_info, table->key_info->key_length); - if (table->file->index_read_idx_map(table->record[0], 0, user_key, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + if (table->file->ha_index_read_idx_map(table->record[0], 0, user_key, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) { /* The following should never happen as we first check the in memory @@ -2840,10 +2841,10 @@ static int replace_routine_table(THD *th TRUE); store_record(table,record[1]); // store at pos 1 - if (table->file->index_read_idx_map(table->record[0], 0, - (uchar*) table->field[0]->ptr, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + if (table->file->ha_index_read_idx_map(table->record[0], 0, + (uchar*) table->field[0]->ptr, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) { /* The following should never happen as we first check the in memory @@ -3548,7 +3549,7 @@ static my_bool grant_load_procs_priv(TAB p_table->file->ha_index_init(0, 1); p_table->use_all_columns(); - if (!p_table->file->index_first(p_table->record[0])) + if (!p_table->file->ha_index_first(p_table->record[0])) { memex_ptr= &memex; my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr); @@ -3600,7 +3601,7 @@ static my_bool grant_load_procs_priv(TAB goto end_unlock; } } - while (!p_table->file->index_next(p_table->record[0])); + while (!p_table->file->ha_index_next(p_table->record[0])); } /* Return ok */ return_val= 0; @@ -3650,7 +3651,7 @@ static my_bool grant_load(THD *thd, TABL t_table->use_all_columns(); c_table->use_all_columns(); - if (!t_table->file->index_first(t_table->record[0])) + if (!t_table->file->ha_index_first(t_table->record[0])) { memex_ptr= &memex; my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr); @@ -3685,7 +3686,7 @@ static my_bool grant_load(THD *thd, TABL goto end_unlock; } } - while (!t_table->file->index_next(t_table->record[0])); + while (!t_table->file->ha_index_next(t_table->record[0])); } return_val=0; // Return ok @@ -3957,6 +3958,8 @@ err: { char command[128]; get_privilege_desc(command, sizeof(command), want_access); + status_var_increment(thd->status_var.access_denied_errors); + my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), command, sctx->priv_user, @@ -5203,9 +5206,9 @@ static int handle_grant_table(TABLE_LIST table->key_info->key_part[1].store_length); key_copy(user_key, table->record[0], table->key_info, key_prefix_length); - if ((error= table->file->index_read_idx_map(table->record[0], 0, - user_key, (key_part_map)3, - HA_READ_KEY_EXACT))) + if ((error= table->file->ha_index_read_idx_map(table->record[0], 0, + user_key, (key_part_map)3, + HA_READ_KEY_EXACT))) { if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) { @@ -5240,7 +5243,7 @@ static int handle_grant_table(TABLE_LIST DBUG_PRINT("info",("scan table: '%s' search: '%s'@'%s'", table->s->table_name.str, user_str, host_str)); #endif - while ((error= table->file->rnd_next(table->record[0])) != + while ((error= table->file->ha_rnd_next(table->record[0])) != HA_ERR_END_OF_FILE) { if (error) === modified file 'sql/sql_base.cc' --- a/sql/sql_base.cc 2009-09-07 20:50:10 +0000 +++ b/sql/sql_base.cc 2009-10-19 17:14:48 +0000 @@ -1373,6 +1373,12 @@ bool close_thread_table(THD *thd, TABLE DBUG_PRINT("tcache", ("table: '%s'.'%s' 0x%lx", table->s->db.str, table->s->table_name.str, (long) table)); + if (table->file) + { + table->file->update_global_table_stats(); + table->file->update_global_index_stats(); + } + *table_ptr=table->next; /* When closing a MERGE parent or child table, detach the children first. @@ -1902,6 +1908,13 @@ void close_temporary(TABLE *table, bool DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'", table->s->db.str, table->s->table_name.str)); + /* in_use is not set for replication temporary tables during shutdown */ + if (table->in_use) + { + table->file->update_global_table_stats(); + table->file->update_global_index_stats(); + } + free_io_cache(table); closefrm(table, 0); if (delete_table) === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2009-09-15 10:46:35 +0000 +++ b/sql/sql_class.cc 2009-10-19 17:14:48 +0000 @@ -615,6 +615,7 @@ THD::THD() mysys_var=0; binlog_evt_union.do_union= FALSE; enable_slow_log= 0; + #ifndef DBUG_OFF dbug_sentry=THD_SENTRY_MAGIC; #endif @@ -817,7 +818,63 @@ void THD::init(void) update_charset(); reset_current_stmt_binlog_row_based(); bzero((char *) &status_var, sizeof(status_var)); + bzero((char *) &org_status_var, sizeof(org_status_var)); sql_log_bin_toplevel= options & OPTION_BIN_LOG; + select_commands= update_commands= other_commands= 0; + /* Set to handle counting of aborted connections */ + userstat_running= opt_userstat_running; + last_global_update_time= current_connect_time= time(NULL); +} + + +/* Updates some status variables to be used by update_global_user_stats */ + +void THD::update_stats(void) +{ + /* sql_command == SQLCOM_END in case of parse errors or quit */ + if (lex->sql_command != SQLCOM_END) + { + /* The replication thread has the COM_CONNECT command */ + DBUG_ASSERT(command == COM_QUERY || command == COM_CONNECT); + + /* A SQL query. */ + if (lex->sql_command == SQLCOM_SELECT) + select_commands++; + else if (! sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) + { + /* Ignore 'SHOW ' commands */ + } + else if (is_update_query(lex->sql_command)) + update_commands++; + else + other_commands++; + } +} + + +void THD::update_all_stats() +{ + time_t save_time; + ulonglong end_cpu_time, end_utime; + double busy_time, cpu_time; + + /* This is set at start of query if opt_userstat_running was set */ + if (!userstat_running) + return; + + end_cpu_time= my_getcputime(); + end_utime= my_micro_time_and_time(&save_time); + busy_time= (end_utime - start_utime) / 1000000.0; + cpu_time= (end_cpu_time - start_cpu_time) / 10000000.0; + /* In case there are bad values, 2629743 is the #seconds in a month. */ + if (cpu_time > 2629743.0) + cpu_time= 0; + status_var_add(status_var.cpu_time, cpu_time); + status_var_add(status_var.busy_time, busy_time); + + /* Updates THD stats and the global user stats. */ + update_stats(); + update_global_user_stats(this, TRUE, save_time); } @@ -984,9 +1041,8 @@ THD::~THD() from_var from this array NOTES - This function assumes that all variables are long/ulong. - If this assumption will change, then we have to explictely add - the other variables after the while loop + This function assumes that all variables at start are long/ulong and + other types are handled explicitely */ void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var) @@ -998,6 +1054,13 @@ void add_to_status(STATUS_VAR *to_var, S while (to != end) *(to++)+= *(from++); + + /* Handle the not ulong variables. See end of system_status_var */ + to_var->bytes_received= from_var->bytes_received; + to_var->bytes_sent+= from_var->bytes_sent; + to_var->binlog_bytes_written= from_var->binlog_bytes_written; + to_var->cpu_time+= from_var->cpu_time; + to_var->busy_time+= from_var->busy_time; } /* @@ -1010,7 +1073,8 @@ void add_to_status(STATUS_VAR *to_var, S dec_var minus this array NOTE - This function assumes that all variables are long/ulong. + This function assumes that all variables at start are long/ulong and + other types are handled explicitely */ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, @@ -1023,6 +1087,14 @@ void add_diff_to_status(STATUS_VAR *to_v while (to != end) *(to++)+= *(from++) - *(dec++); + + to_var->bytes_received= (from_var->bytes_received - + dec_var->bytes_received); + to_var->bytes_sent+= from_var->bytes_sent - dec_var->bytes_sent; + to_var->binlog_bytes_written= (from_var->binlog_bytes_written - + dec_var->binlog_bytes_written); + to_var->cpu_time+= from_var->cpu_time - dec_var->cpu_time; + to_var->busy_time+= from_var->busy_time - dec_var->busy_time; } #define SECONDS_TO_WAIT_FOR_KILL 2 @@ -2773,7 +2845,8 @@ void thd_increment_bytes_sent(ulong leng { THD *thd=current_thd; if (likely(thd != 0)) - { /* current_thd==0 when close_connection() calls net_send_error() */ + { + /* current_thd == 0 when close_connection() calls net_send_error() */ thd->status_var.bytes_sent+= length; } } === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2009-09-15 10:46:35 +0000 +++ b/sql/sql_class.h 2009-10-19 17:14:48 +0000 @@ -415,8 +415,6 @@ struct system_variables typedef struct system_status_var { - ulonglong bytes_received; - ulonglong bytes_sent; ulong com_other; ulong com_stat[(uint) SQLCOM_END]; ulong created_tmp_disk_tables; @@ -455,6 +453,8 @@ typedef struct system_status_var ulong select_range_count; ulong select_range_check_count; ulong select_scan_count; + ulong rows_read; + ulong rows_sent; ulong long_query_count; ulong filesort_merge_passes; ulong filesort_range_count; @@ -472,6 +472,9 @@ typedef struct system_status_var Number of statements sent from the client */ ulong questions; + ulong empty_queries; + ulong access_denied_errors; /* Can only be 0 or 1 */ + ulong lost_connections; /* IMPORTANT! SEE last_system_status_var DEFINITION BELOW. @@ -480,12 +483,16 @@ typedef struct system_status_var Status variables which it does not make sense to add to global status variable counter */ + ulonglong bytes_received; + ulonglong bytes_sent; + ulonglong binlog_bytes_written; double last_query_cost; + double cpu_time, busy_time; } STATUS_VAR; /* This is used for 'SHOW STATUS'. It must be updated to the last ulong - variable in system_status_var which is makes sens to add to the global + variable in system_status_var which is makes sense to add to the global counter */ @@ -1299,6 +1306,7 @@ public: struct my_rnd_struct rand; // used for authentication struct system_variables variables; // Changeable local variables struct system_status_var status_var; // Per thread statistic vars + struct system_status_var org_status_var; // For user statistics struct system_status_var *initial_status_var; /* used by show status */ THR_LOCK_INFO lock_info; // Locking info of this thread THR_LOCK_OWNER main_lock_id; // To use for conventional queries @@ -1399,6 +1407,8 @@ public: uint in_sub_stmt; /* TRUE when the current top has SQL_LOG_BIN ON */ bool sql_log_bin_toplevel; + /* True when opt_userstat_running is set at start of query */ + bool userstat_running; /* container for handler's private per-connection data */ Ha_data ha_data[MAX_HA]; @@ -1842,6 +1852,21 @@ public: */ LOG_INFO* current_linfo; NET* slave_net; // network connection from slave -> m. + + /* + Used to update global user stats. The global user stats are updated + occasionally with the 'diff' variables. After the update, the 'diff' + variables are reset to 0. + */ + /* Time when the current thread connected to MySQL. */ + time_t current_connect_time; + /* Last time when THD stats were updated in global_user_stats. */ + time_t last_global_update_time; + /* Number of commands not reflected in global_user_stats yet. */ + uint select_commands, update_commands, other_commands; + ulonglong start_cpu_time; + ulonglong start_bytes_received; + /* Used by the sys_var class to store temporary values */ union { @@ -1902,6 +1927,8 @@ public: alloc_root. */ void init_for_queries(); + void update_all_stats(); + void update_stats(void); void change_user(void); void cleanup(void); void cleanup_after_query(); @@ -2319,7 +2346,6 @@ private: MEM_ROOT main_mem_root; }; - /** A short cut for thd->main_da.set_ok_status(). */ inline void === modified file 'sql/sql_connect.cc' --- a/sql/sql_connect.cc 2009-09-07 20:50:10 +0000 +++ b/sql/sql_connect.cc 2009-10-19 17:14:48 +0000 @@ -20,6 +20,13 @@ #include "mysql_priv.h" +HASH global_user_stats, global_client_stats, global_table_stats; +HASH global_index_stats; +/* Protects the above global stats */ +extern pthread_mutex_t LOCK_global_user_client_stats; +extern pthread_mutex_t LOCK_global_table_stats; +extern pthread_mutex_t LOCK_global_index_stats; + #ifdef HAVE_OPENSSL /* Without SSL the handshake consists of one packet. This packet @@ -459,6 +466,7 @@ check_user(THD *thd, enum enum_server_co check_for_max_user_connections(thd, thd->user_connect)) { /* The error is set in check_for_max_user_connections(). */ + status_var_increment(denied_connections); DBUG_RETURN(1); } @@ -470,6 +478,7 @@ check_user(THD *thd, enum enum_server_co /* mysql_change_db() has pushed the error message. */ if (thd->user_connect) decrease_user_connections(thd->user_connect); + status_var_increment(thd->status_var.access_denied_errors); DBUG_RETURN(1); } } @@ -493,6 +502,8 @@ check_user(THD *thd, enum enum_server_co thd->main_security_ctx.user, thd->main_security_ctx.host_or_ip, passwd_len ? ER(ER_YES) : ER(ER_NO)); + status_var_increment(thd->status_var.access_denied_errors); + DBUG_RETURN(1); #endif /* NO_EMBEDDED_ACCESS_CHECKS */ } @@ -520,10 +531,14 @@ extern "C" void free_user(struct user_co void init_max_user_conn(void) { #ifndef NO_EMBEDDED_ACCESS_CHECKS - (void) hash_init(&hash_user_connections,system_charset_info,max_connections, - 0,0, - (hash_get_key) get_key_conn, (hash_free_key) free_user, - 0); + if (hash_init(&hash_user_connections,system_charset_info,max_connections, + 0,0, + (hash_get_key) get_key_conn, (hash_free_key) free_user, + 0)) + { + sql_print_error("Initializing hash_user_connections failed."); + exit(1); + } #endif } @@ -576,6 +591,445 @@ void reset_mqh(LEX_USER *lu, bool get_th #endif /* NO_EMBEDDED_ACCESS_CHECKS */ } +/***************************************************************************** + Handle users statistics +*****************************************************************************/ + +/* 'mysql_system_user' is used for when the user is not defined for a THD. */ +static const char mysql_system_user[]= "#mysql_system#"; + +// Returns 'user' if it's not NULL. Returns 'mysql_system_user' otherwise. +static const char * get_valid_user_string(char* user) +{ + return user ? user : mysql_system_user; +} + +/* + Returns string as 'IP' for the client-side of the connection represented by + 'client'. Does not allocate memory. May return "". +*/ + +static const char *get_client_host(THD *client) +{ + return client->security_ctx->host_or_ip[0] ? + client->security_ctx->host_or_ip : + client->security_ctx->host ? client->security_ctx->host : ""; +} + +extern "C" uchar *get_key_user_stats(USER_STATS *user_stats, size_t *length, + my_bool not_used __attribute__((unused))) +{ + *length= user_stats->user_name_length; + return (uchar*) user_stats->user; +} + +void free_user_stats(USER_STATS* user_stats) +{ + my_free(user_stats, MYF(0)); +} + +void init_user_stats(USER_STATS *user_stats, + const char *user, + size_t user_length, + const char *priv_user, + uint total_connections, + uint concurrent_connections, + time_t connected_time, + double busy_time, + double cpu_time, + ulonglong bytes_received, + ulonglong bytes_sent, + ulonglong binlog_bytes_written, + ha_rows rows_sent, + ha_rows rows_read, + ha_rows rows_inserted, + ha_rows rows_deleted, + ha_rows rows_updated, + ulonglong select_commands, + ulonglong update_commands, + ulonglong other_commands, + ulonglong commit_trans, + ulonglong rollback_trans, + ulonglong denied_connections, + ulonglong lost_connections, + ulonglong access_denied_errors, + ulonglong empty_queries) +{ + DBUG_ENTER("init_user_stats"); + DBUG_PRINT("enter", ("user: %s priv_user: %s", user, priv_user)); + + user_length= min(user_length, sizeof(user_stats->user)-1); + memcpy(user_stats->user, user, user_length); + user_stats->user[user_length]= 0; + user_stats->user_name_length= user_length; + strmake(user_stats->priv_user, priv_user, sizeof(user_stats->priv_user)-1); + + user_stats->total_connections= total_connections; + user_stats->concurrent_connections= concurrent_connections; + user_stats->connected_time= connected_time; + user_stats->busy_time= busy_time; + user_stats->cpu_time= cpu_time; + user_stats->bytes_received= bytes_received; + user_stats->bytes_sent= bytes_sent; + user_stats->binlog_bytes_written= binlog_bytes_written; + user_stats->rows_sent= rows_sent; + user_stats->rows_updated= rows_updated; + user_stats->rows_read= rows_read; + user_stats->select_commands= select_commands; + user_stats->update_commands= update_commands; + user_stats->other_commands= other_commands; + user_stats->commit_trans= commit_trans; + user_stats->rollback_trans= rollback_trans; + user_stats->denied_connections= denied_connections; + user_stats->lost_connections= lost_connections; + user_stats->access_denied_errors= access_denied_errors; + user_stats->empty_queries= empty_queries; + DBUG_VOID_RETURN; +} + + +#ifdef COMPLEAT_PATCH_NOT_ADDED_YET + +void add_user_stats(USER_STATS *user_stats, + uint total_connections, + uint concurrent_connections, + time_t connected_time, + double busy_time, + double cpu_time, + ulonglong bytes_received, + ulonglong bytes_sent, + ulonglong binlog_bytes_written, + ha_rows rows_sent, + ha_rows rows_read, + ha_rows rows_inserted, + ha_rows rows_deleted, + ha_rows rows_updated, + ulonglong select_commands, + ulonglong update_commands, + ulonglong other_commands, + ulonglong commit_trans, + ulonglong rollback_trans, + ulonglong denied_connections, + ulonglong lost_connections, + ulonglong access_denied_errors, + ulonglong empty_queries) +{ + user_stats->total_connections+= total_connections; + user_stats->concurrent_connections+= concurrent_connections; + user_stats->connected_time+= connected_time; + user_stats->busy_time+= busy_time; + user_stats->cpu_time+= cpu_time; + user_stats->bytes_received+= bytes_received; + user_stats->bytes_sent+= bytes_sent; + user_stats->binlog_bytes_written+= binlog_bytes_written; + user_stats->rows_sent+= rows_sent; + user_stats->rows_inserted+= rows_inserted; + user_stats->rows_deleted+= rows_deleted; + user_stats->rows_updated+= rows_updated; + user_stats->rows_read+= rows_read; + user_stats->select_commands+= select_commands; + user_stats->update_commands+= update_commands; + user_stats->other_commands+= other_commands; + user_stats->commit_trans+= commit_trans; + user_stats->rollback_trans+= rollback_trans; + user_stats->denied_connections+= denied_connections; + user_stats->lost_connections+= lost_connections; + user_stats->access_denied_errors+= access_denied_errors; + user_stats->empty_queries+= empty_queries; +} +#endif + + +void init_global_user_stats(void) +{ + if (hash_init(&global_user_stats, system_charset_info, max_connections, + 0, 0, (hash_get_key) get_key_user_stats, + (hash_free_key)free_user_stats, 0)) + { + sql_print_error("Initializing global_user_stats failed."); + exit(1); + } +} + +void init_global_client_stats(void) +{ + if (hash_init(&global_client_stats, system_charset_info, max_connections, + 0, 0, (hash_get_key) get_key_user_stats, + (hash_free_key)free_user_stats, 0)) + { + sql_print_error("Initializing global_client_stats failed."); + exit(1); + } +} + +extern "C" uchar *get_key_table_stats(TABLE_STATS *table_stats, size_t *length, + my_bool not_used __attribute__((unused))) +{ + *length= table_stats->table_name_length; + return (uchar*) table_stats->table; +} + +extern "C" void free_table_stats(TABLE_STATS* table_stats) +{ + my_free(table_stats, MYF(0)); +} + +void init_global_table_stats(void) +{ + if (hash_init(&global_table_stats, system_charset_info, max_connections, + 0, 0, (hash_get_key) get_key_table_stats, + (hash_free_key)free_table_stats, 0)) { + sql_print_error("Initializing global_table_stats failed."); + exit(1); + } +} + +extern "C" uchar *get_key_index_stats(INDEX_STATS *index_stats, size_t *length, + my_bool not_used __attribute__((unused))) +{ + *length= index_stats->index_name_length; + return (uchar*) index_stats->index; +} + +extern "C" void free_index_stats(INDEX_STATS* index_stats) +{ + my_free(index_stats, MYF(0)); +} + +void init_global_index_stats(void) +{ + if (hash_init(&global_index_stats, system_charset_info, max_connections, + 0, 0, (hash_get_key) get_key_index_stats, + (hash_free_key)free_index_stats, 0)) + { + sql_print_error("Initializing global_index_stats failed."); + exit(1); + } +} + + +void free_global_user_stats(void) +{ + hash_free(&global_user_stats); +} + +void free_global_table_stats(void) +{ + hash_free(&global_table_stats); +} + +void free_global_index_stats(void) +{ + hash_free(&global_index_stats); +} + +void free_global_client_stats(void) +{ + hash_free(&global_client_stats); +} + +/* + Increments the global stats connection count for an entry from + global_client_stats or global_user_stats. Returns 0 on success + and 1 on error. +*/ + +static bool increment_count_by_name(const char *name, size_t name_length, + const char *role_name, + HASH *users_or_clients, THD *thd) +{ + USER_STATS *user_stats; + + if (!(user_stats= (USER_STATS*) hash_search(users_or_clients, (uchar*) name, + name_length))) + { + /* First connection for this user or client */ + if (!(user_stats= ((USER_STATS*) + my_malloc(sizeof(USER_STATS), + MYF(MY_WME | MY_ZEROFILL))))) + return TRUE; // Out of memory + + init_user_stats(user_stats, name, name_length, role_name, + 0, 0, // connections + 0, 0, 0, // time + 0, 0, 0, // bytes sent, received and written + 0, 0, // Rows sent and read + 0, 0, 0, // rows inserted, deleted and updated + 0, 0, 0, // select, update and other commands + 0, 0, // commit and rollback trans + thd->status_var.access_denied_errors, + 0, // lost connections + 0, // access denied errors + 0); // empty queries + + if (my_hash_insert(users_or_clients, (uchar*)user_stats)) + { + my_free(user_stats, 0); + return TRUE; // Out of memory + } + } + user_stats->total_connections++; + return FALSE; +} + + +/* + Increments the global user and client stats connection count. + + @param use_lock if true, LOCK_global_user_client_stats will be locked + + @retval 0 ok + @retval 1 error. +*/ + +#ifndef EMBEDDED_LIBRARY +static bool increment_connection_count(THD* thd, bool use_lock) +{ + const char *user_string= get_valid_user_string(thd->main_security_ctx.user); + const char *client_string= get_client_host(thd); + bool return_value= FALSE; + + if (!thd->userstat_running) + return FALSE; + + if (use_lock) + pthread_mutex_lock(&LOCK_global_user_client_stats); + + if (increment_count_by_name(user_string, strlen(user_string), user_string, + &global_user_stats, thd)) + { + return_value= TRUE; + goto end; + } + if (increment_count_by_name(client_string, strlen(client_string), + user_string, &global_client_stats, thd)) + { + return_value= TRUE; + goto end; + } + +end: + if (use_lock) + pthread_mutex_unlock(&LOCK_global_user_client_stats); + return return_value; +} +#endif + +/* + Used to update the global user and client stats +*/ + +static void update_global_user_stats_with_user(THD *thd, + USER_STATS *user_stats, + time_t now) +{ + DBUG_ASSERT(thd->userstat_running); + + user_stats->connected_time+= now - thd->last_global_update_time; + user_stats->busy_time+= (thd->status_var.busy_time - + thd->org_status_var.busy_time); + user_stats->cpu_time+= (thd->status_var.cpu_time - + thd->org_status_var.cpu_time); + /* + This is handle specially as bytes_recieved is incremented BEFORE + org_status_var is copied. + */ + user_stats->bytes_received+= (thd->org_status_var.bytes_received- + thd->start_bytes_received); + user_stats->bytes_sent+= (thd->status_var.bytes_sent - + thd->org_status_var.bytes_sent); + user_stats->binlog_bytes_written+= + (thd->status_var.binlog_bytes_written - + thd->org_status_var.binlog_bytes_written); + user_stats->rows_read+= (thd->status_var.rows_read - + thd->org_status_var.rows_read); + user_stats->rows_sent+= (thd->status_var.rows_sent - + thd->org_status_var.rows_sent); + user_stats->rows_inserted+= (thd->status_var.ha_write_count - + thd->org_status_var.ha_write_count); + user_stats->rows_deleted+= (thd->status_var.ha_delete_count - + thd->org_status_var.ha_delete_count); + user_stats->rows_updated+= (thd->status_var.ha_update_count - + thd->org_status_var.ha_update_count); + user_stats->select_commands+= thd->select_commands; + user_stats->update_commands+= thd->update_commands; + user_stats->other_commands+= thd->other_commands; + user_stats->commit_trans+= (thd->status_var.ha_commit_count - + thd->org_status_var.ha_commit_count); + user_stats->rollback_trans+= (thd->status_var.ha_rollback_count + + thd->status_var.ha_savepoint_rollback_count - + thd->org_status_var.ha_rollback_count - + thd->org_status_var. + ha_savepoint_rollback_count); + user_stats->access_denied_errors+= + (thd->status_var.access_denied_errors - + thd->org_status_var.access_denied_errors); + user_stats->empty_queries+= (thd->status_var.empty_queries - + thd->org_status_var.empty_queries); + + /* The following can only contain 0 or 1 and then connection ends */ + user_stats->denied_connections+= thd->status_var.access_denied_errors; + user_stats->lost_connections+= thd->status_var.lost_connections; +} + + +/* Updates the global stats of a user or client */ +void update_global_user_stats(THD *thd, bool create_user, time_t now) +{ + const char *user_string, *client_string; + USER_STATS *user_stats; + size_t user_string_length, client_string_length; + DBUG_ASSERT(thd->userstat_running); + + user_string= get_valid_user_string(thd->main_security_ctx.user); + user_string_length= strlen(user_string); + client_string= get_client_host(thd); + client_string_length= strlen(client_string); + + pthread_mutex_lock(&LOCK_global_user_client_stats); + + // Update by user name + if ((user_stats= (USER_STATS*) hash_search(&global_user_stats, + (uchar*) user_string, + user_string_length))) + { + /* Found user. */ + update_global_user_stats_with_user(thd, user_stats, now); + } + else + { + /* Create the entry */ + if (create_user) + { + increment_count_by_name(user_string, user_string_length, user_string, + &global_user_stats, thd); + } + } + + /* Update by client IP */ + if ((user_stats= (USER_STATS*)hash_search(&global_client_stats, + (uchar*) client_string, + client_string_length))) + { + // Found by client IP + update_global_user_stats_with_user(thd, user_stats, now); + } + else + { + // Create the entry + if (create_user) + { + increment_count_by_name(client_string, client_string_length, + user_string, &global_client_stats, thd); + } + } + /* Reset variables only used for counting */ + thd->select_commands= thd->update_commands= thd->other_commands= 0; + thd->last_global_update_time= now; + + pthread_mutex_unlock(&LOCK_global_user_client_stats); +} + void thd_init_client_charset(THD *thd, uint cs_number) { @@ -970,6 +1424,14 @@ bool login_connection(THD *thd) /* Connect completed, set read/write timeouts back to default */ my_net_set_read_timeout(net, thd->variables.net_read_timeout); my_net_set_write_timeout(net, thd->variables.net_write_timeout); + + /* Updates global user connection stats. */ + if (increment_connection_count(thd, TRUE)) + { + net_send_error(thd, ER_OUTOFMEMORY); // Out of memory + DBUG_RETURN(1); + } + DBUG_RETURN(0); } @@ -991,6 +1453,7 @@ void end_connection(THD *thd) if (thd->killed || (net->error && net->vio != 0)) { statistic_increment(aborted_threads,&LOCK_status); + status_var_increment(thd->status_var.lost_connections); } if (net->error && net->vio != 0) @@ -1117,10 +1580,14 @@ pthread_handler_t handle_one_connection( for (;;) { NET *net= &thd->net; + bool create_user= TRUE; lex_start(thd); if (login_connection(thd)) + { + create_user= FALSE; goto end_thread; + } prepare_new_connection_state(thd); @@ -1134,12 +1601,14 @@ pthread_handler_t handle_one_connection( end_thread: close_connection(thd, 0, 1); + if (thd->userstat_running) + update_global_user_stats(thd, create_user, time(NULL)); + if (thd->scheduler->end_thread(thd,1)) return 0; // Probably no-threads /* - If end_thread() returns, we are either running with - thread-handler=no-threads or this thread has been schedule to + If end_thread() returns, this thread has been schedule to handle the next connection. */ thd= current_thd; === modified file 'sql/sql_cursor.cc' --- a/sql/sql_cursor.cc 2008-12-10 14:16:21 +0000 +++ b/sql/sql_cursor.cc 2009-10-19 17:14:48 +0000 @@ -655,7 +655,7 @@ void Materialized_cursor::fetch(ulong nu result->begin_dataset(); for (fetch_limit+= num_rows; fetch_count < fetch_limit; fetch_count++) { - if ((res= table->file->rnd_next(table->record[0]))) + if ((res= table->file->ha_rnd_next(table->record[0]))) break; /* Send data only if the read was successful. */ result->send_data(item_list); === modified file 'sql/sql_handler.cc' --- a/sql/sql_handler.cc 2009-07-15 23:23:57 +0000 +++ b/sql/sql_handler.cc 2009-10-19 17:14:48 +0000 @@ -565,8 +565,8 @@ retry: if (table->file->inited != handler::NONE) { error=keyname ? - table->file->index_next(table->record[0]) : - table->file->rnd_next(table->record[0]); + table->file->ha_index_next(table->record[0]) : + table->file->ha_rnd_next(table->record[0]); break; } /* else fall through */ @@ -575,13 +575,13 @@ retry: { table->file->ha_index_or_rnd_end(); table->file->ha_index_init(keyno, 1); - error= table->file->index_first(table->record[0]); + error= table->file->ha_index_first(table->record[0]); } else { table->file->ha_index_or_rnd_end(); if (!(error= table->file->ha_rnd_init(1))) - error= table->file->rnd_next(table->record[0]); + error= table->file->ha_rnd_next(table->record[0]); } mode=RNEXT; break; @@ -589,7 +589,7 @@ retry: DBUG_ASSERT(keyname != 0); if (table->file->inited != handler::NONE) { - error=table->file->index_prev(table->record[0]); + error=table->file->ha_index_prev(table->record[0]); break; } /* else fall through */ @@ -597,13 +597,13 @@ retry: DBUG_ASSERT(keyname != 0); table->file->ha_index_or_rnd_end(); table->file->ha_index_init(keyno, 1); - error= table->file->index_last(table->record[0]); + error= table->file->ha_index_last(table->record[0]); mode=RPREV; break; case RNEXT_SAME: /* Continue scan on "(keypart1,keypart2,...)=(c1, c2, ...) */ DBUG_ASSERT(keyname != 0); - error= table->file->index_next_same(table->record[0], key, key_len); + error= table->file->ha_index_next_same(table->record[0], key, key_len); break; case RKEY: { @@ -643,8 +643,8 @@ retry: table->file->ha_index_or_rnd_end(); table->file->ha_index_init(keyno, 1); key_copy(key, table->record[0], table->key_info + keyno, key_len); - error= table->file->index_read_map(table->record[0], - key, keypart_map, ha_rkey_mode); + error= table->file->ha_index_read_map(table->record[0], + key, keypart_map, ha_rkey_mode); mode=rkey_to_rnext[(int)ha_rkey_mode]; break; } === modified file 'sql/sql_help.cc' --- a/sql/sql_help.cc 2009-09-07 20:50:10 +0000 +++ b/sql/sql_help.cc 2009-10-19 17:14:48 +0000 @@ -294,13 +294,13 @@ int get_topics_for_keyword(THD *thd, TAB rkey_id->store((longlong) key_id, TRUE); rkey_id->get_key_image(buff, rkey_id->pack_length(), Field::itRAW); - int key_res= relations->file->index_read_map(relations->record[0], - buff, (key_part_map) 1, - HA_READ_KEY_EXACT); + int key_res= relations->file->ha_index_read_map(relations->record[0], + buff, (key_part_map) 1, + HA_READ_KEY_EXACT); for ( ; !key_res && key_id == (int16) rkey_id->val_int() ; - key_res= relations->file->index_next(relations->record[0])) + key_res= relations->file->ha_index_next(relations->record[0])) { uchar topic_id_buff[8]; longlong topic_id= rtopic_id->val_int(); @@ -308,8 +308,8 @@ int get_topics_for_keyword(THD *thd, TAB field->store((longlong) topic_id, TRUE); field->get_key_image(topic_id_buff, field->pack_length(), Field::itRAW); - if (!topics->file->index_read_map(topics->record[0], topic_id_buff, - (key_part_map)1, HA_READ_KEY_EXACT)) + if (!topics->file->ha_index_read_map(topics->record[0], topic_id_buff, + (key_part_map)1, HA_READ_KEY_EXACT)) { memorize_variant_topic(thd,topics,count,find_fields, names,name,description,example); === modified file 'sql/sql_insert.cc' --- a/sql/sql_insert.cc 2009-09-07 20:50:10 +0000 +++ b/sql/sql_insert.cc 2009-10-19 17:14:48 +0000 @@ -1425,7 +1425,7 @@ int write_record(THD *thd, TABLE *table, goto err; if (table->file->ha_table_flags() & HA_DUPLICATE_POS) { - if (table->file->rnd_pos(table->record[1],table->file->dup_ref)) + if (table->file->ha_rnd_pos(table->record[1],table->file->dup_ref)) goto err; } else @@ -1446,9 +1446,10 @@ int write_record(THD *thd, TABLE *table, } } key_copy((uchar*) key,table->record[0],table->key_info+key_nr,0); - if ((error=(table->file->index_read_idx_map(table->record[1],key_nr, - (uchar*) key, HA_WHOLE_KEY, - HA_READ_KEY_EXACT)))) + if ((error= (table->file->ha_index_read_idx_map(table->record[1], + key_nr, (uchar*) key, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT)))) goto err; } if (info->handle_duplicates == DUP_UPDATE) === modified file 'sql/sql_lex.h' --- a/sql/sql_lex.h 2009-09-15 10:46:35 +0000 +++ b/sql/sql_lex.h 2009-10-19 17:14:48 +0000 @@ -118,6 +118,8 @@ enum enum_sql_command { SQLCOM_SHOW_CREATE_TRIGGER, SQLCOM_ALTER_DB_UPGRADE, SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES, + SQLCOM_SHOW_USER_STATS, SQLCOM_SHOW_TABLE_STATS, SQLCOM_SHOW_INDEX_STATS, + SQLCOM_SHOW_CLIENT_STATS, /* When a command is added here, be sure it's also added in mysqld.cc === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2009-09-15 10:46:35 +0000 +++ b/sql/sql_parse.cc 2009-10-19 17:14:48 +0000 @@ -331,10 +331,14 @@ void init_update_queries(void) sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_PROFILE]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_CLIENT_STATS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_USER_STATS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_TABLE_STATS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_INDEX_STATS]= CF_STATUS_COMMAND; - sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND | - CF_SHOW_TABLE_COMMAND | - CF_REEXECUTION_FRAGILE); + sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND | + CF_SHOW_TABLE_COMMAND | + CF_REEXECUTION_FRAGILE); sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND | CF_SHOW_TABLE_COMMAND | CF_REEXECUTION_FRAGILE); @@ -549,7 +553,6 @@ end: DBUG_RETURN(0); } - /** @brief Check access privs for a MERGE table and fix children lock types. @@ -801,6 +804,8 @@ bool do_command(THD *thd) net_new_transaction(net); + /* Save for user statistics */ + thd->start_bytes_received= thd->status_var.bytes_received; packet_length= my_net_read(net); #if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.start_new_query(); @@ -1324,7 +1329,7 @@ bool dispatch_command(enum enum_server_c table_list.select_lex= &(thd->lex->select_lex); lex_start(thd); - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, opt_userstat_running); thd->lex-> select_lex.table_list.link_in_list((uchar*) &table_list, @@ -1609,6 +1614,9 @@ bool dispatch_command(enum enum_server_c /* Free tables */ close_thread_tables(thd); + /* Update status; Must be done after close_thread_tables */ + thd->update_all_stats(); + log_slow_statement(thd); thd_proc_info(thd, "cleaning up"); @@ -1777,6 +1785,12 @@ int prepare_schema_table(THD *thd, LEX * thd->profiling.discard_current_query(); #endif break; + case SCH_USER_STATS: + case SCH_CLIENT_STATS: + if (check_global_access(thd, SUPER_ACL | PROCESS_ACL)) + DBUG_RETURN(1); + case SCH_TABLE_STATS: + case SCH_INDEX_STATS: case SCH_OPEN_TABLES: case SCH_VARIABLES: case SCH_STATUS: @@ -2218,6 +2232,10 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_COLLATIONS: case SQLCOM_SHOW_STORAGE_ENGINES: case SQLCOM_SHOW_PROFILE: + case SQLCOM_SHOW_CLIENT_STATS: + case SQLCOM_SHOW_USER_STATS: + case SQLCOM_SHOW_TABLE_STATS: + case SQLCOM_SHOW_INDEX_STATS: case SQLCOM_SELECT: thd->status_var.last_query_cost= 0.0; if (all_tables) @@ -5059,6 +5077,10 @@ static bool execute_sqlcom_select(THD *t delete result; } } + /* Count number of empty select queries */ + if (!thd->sent_row_count) + status_var_increment(thd->status_var.empty_queries); + status_var_add(thd->status_var.rows_sent, thd->sent_row_count); return res; } @@ -5220,6 +5242,7 @@ check_access(THD *thd, ulong want_access if (!no_errors) { const char *db_name= db ? db : thd->db; + status_var_increment(thd->status_var.access_denied_errors); my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), sctx->priv_user, sctx->priv_host, db_name); } @@ -5252,12 +5275,15 @@ check_access(THD *thd, ulong want_access { // We can never grant this DBUG_PRINT("error",("No possible access")); if (!no_errors) + { + status_var_increment(thd->status_var.access_denied_errors); my_error(ER_ACCESS_DENIED_ERROR, MYF(0), sctx->priv_user, sctx->priv_host, (thd->password ? ER(ER_YES) : ER(ER_NO))); /* purecov: tested */ + } DBUG_RETURN(TRUE); /* purecov: tested */ } @@ -5283,11 +5309,14 @@ check_access(THD *thd, ulong want_access DBUG_PRINT("error",("Access denied")); if (!no_errors) + { + status_var_increment(thd->status_var.access_denied_errors); my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), sctx->priv_user, sctx->priv_host, (db ? db : (thd->db ? thd->db : "unknown"))); /* purecov: tested */ + } DBUG_RETURN(TRUE); /* purecov: tested */ } @@ -5316,6 +5345,7 @@ static bool check_show_access(THD *thd, if (!thd->col_access && check_grant_db(thd, dst_db_name)) { + status_var_increment(thd->status_var.access_denied_errors); my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), thd->security_ctx->priv_user, thd->security_ctx->priv_host, @@ -5378,14 +5408,14 @@ check_table_access(THD *thd, ulong want_ { TABLE_LIST *org_tables= tables; TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table(); - uint i= 0; Security_context *sctx= thd->security_ctx, *backup_ctx= thd->security_ctx; + uint i; /* The check that first_not_own_table is not reached is for the case when the given table list refers to the list for prelocking (contains tables of other queries). For simple queries first_not_own_table is 0. */ - for (; i < number && tables != first_not_own_table; + for (i=0; i < number && tables != first_not_own_table; tables= tables->next_global, i++) { if (tables->security_ctx) @@ -5397,9 +5427,12 @@ check_table_access(THD *thd, ulong want_ (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL))) { if (!no_errors) + { + status_var_increment(thd->status_var.access_denied_errors); my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), sctx->priv_user, sctx->priv_host, INFORMATION_SCHEMA_NAME.str); + } return TRUE; } /* @@ -5563,6 +5596,7 @@ bool check_global_access(THD *thd, ulong return 0; get_privilege_desc(command, sizeof(command), want_access); my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command); + status_var_increment(thd->status_var.access_denied_errors); return 1; #else return 0; @@ -5666,7 +5700,7 @@ bool my_yyoverflow(short **yyss, YYSTYPE Call it after we use THD for queries, not before. */ -void mysql_reset_thd_for_next_command(THD *thd) +void mysql_reset_thd_for_next_command(THD *thd, my_bool calculate_userstat) { DBUG_ENTER("mysql_reset_thd_for_next_command"); DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */ @@ -5711,6 +5745,15 @@ void mysql_reset_thd_for_next_command(TH thd->total_warn_count=0; // Warnings for this query thd->rand_used= 0; thd->sent_row_count= thd->examined_row_count= 0; + + /* Copy data for user stats */ + if ((thd->userstat_running= calculate_userstat)) + { + thd->start_cpu_time= my_getcputime(); + memcpy(&thd->org_status_var, &thd->status_var, sizeof(thd->status_var)); + thd->select_commands= thd->update_commands= thd->other_commands= 0; + } + thd->query_plan_flags= QPLAN_INIT; thd->query_plan_fsort_passes= 0; @@ -5909,7 +5952,6 @@ void mysql_parse(THD *thd, const char *i const char ** found_semicolon) { DBUG_ENTER("mysql_parse"); - DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on();); /* @@ -5929,7 +5971,7 @@ void mysql_parse(THD *thd, const char *i FIXME: cleanup the dependencies in the code to simplify this. */ lex_start(thd); - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, opt_userstat_running); if (query_cache_send_result_to_client(thd, (char*) inBuf, length) <= 0) { @@ -6001,10 +6043,11 @@ void mysql_parse(THD *thd, const char *i } else { + /* Update statistics for getting the query from the cache */ + thd->lex->sql_command= SQLCOM_SELECT; /* There are no multi queries in the cache. */ *found_semicolon= NULL; } - DBUG_VOID_RETURN; } @@ -6028,7 +6071,7 @@ bool mysql_test_parse_for_slave(THD *thd Parser_state parser_state(thd, inBuf, length); lex_start(thd); - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, 0); if (!parse_sql(thd, & parser_state, NULL) && all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) @@ -6867,6 +6910,13 @@ bool reload_acl_and_cache(THD *thd, ulon if (flush_error_log()) result=1; } + if (((options & (REFRESH_SLOW_QUERY_LOG | REFRESH_LOG)) == + REFRESH_SLOW_QUERY_LOG)) + { + /* We are only flushing slow query log */ + logger.flush_slow_log(thd); + } + #ifdef HAVE_QUERY_CACHE if (options & REFRESH_QUERY_CACHE_FREE) { @@ -6949,26 +6999,55 @@ bool reload_acl_and_cache(THD *thd, ulon } #endif #ifdef OPENSSL - if (options & REFRESH_DES_KEY_FILE) - { - if (des_key_file && load_des_key_file(des_key_file)) - result= 1; - } + if (options & REFRESH_DES_KEY_FILE) + { + if (des_key_file && load_des_key_file(des_key_file)) + result= 1; + } #endif #ifdef HAVE_REPLICATION - if (options & REFRESH_SLAVE) - { - tmp_write_to_binlog= 0; - pthread_mutex_lock(&LOCK_active_mi); - if (reset_slave(thd, active_mi)) - result=1; - pthread_mutex_unlock(&LOCK_active_mi); - } -#endif - if (options & REFRESH_USER_RESOURCES) - reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */ - *write_to_binlog= tmp_write_to_binlog; - return result; + if (options & REFRESH_SLAVE) + { + tmp_write_to_binlog= 0; + pthread_mutex_lock(&LOCK_active_mi); + if (reset_slave(thd, active_mi)) + result=1; + pthread_mutex_unlock(&LOCK_active_mi); + } +#endif + if (options & REFRESH_USER_RESOURCES) + reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */ + if (options & REFRESH_TABLE_STATS) + { + pthread_mutex_lock(&LOCK_global_table_stats); + free_global_table_stats(); + init_global_table_stats(); + pthread_mutex_unlock(&LOCK_global_table_stats); + } + if (options & REFRESH_INDEX_STATS) + { + pthread_mutex_lock(&LOCK_global_index_stats); + free_global_index_stats(); + init_global_index_stats(); + pthread_mutex_unlock(&LOCK_global_index_stats); + } + if (options & (REFRESH_USER_STATS | REFRESH_CLIENT_STATS)) + { + pthread_mutex_lock(&LOCK_global_user_client_stats); + if (options & REFRESH_USER_STATS) + { + free_global_user_stats(); + init_global_user_stats(); + } + if (options & REFRESH_CLIENT_STATS) + { + free_global_client_stats(); + init_global_client_stats(); + } + pthread_mutex_unlock(&LOCK_global_user_client_stats); + } + *write_to_binlog= tmp_write_to_binlog; + return result; } @@ -7004,7 +7083,6 @@ uint kill_one_thread(THD *thd, ulong id, VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (tmp) { - /* If we're SUPER, we can KILL anything, including system-threads. No further checks. === modified file 'sql/sql_plugin.cc' --- a/sql/sql_plugin.cc 2009-10-01 21:27:39 +0000 +++ b/sql/sql_plugin.cc 2009-10-19 17:14:48 +0000 @@ -1790,10 +1790,10 @@ bool mysql_uninstall_plugin(THD *thd, co table->use_all_columns(); table->field[0]->store(name->str, name->length, system_charset_info); - if (! table->file->index_read_idx_map(table->record[0], 0, - (uchar *)table->field[0]->ptr, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + if (! table->file->ha_index_read_idx_map(table->record[0], 0, + (uchar *)table->field[0]->ptr, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) { int error; /* === modified file 'sql/sql_prepare.cc' --- a/sql/sql_prepare.cc 2009-09-07 20:50:10 +0000 +++ b/sql/sql_prepare.cc 2009-10-19 17:14:48 +0000 @@ -2067,14 +2067,13 @@ void mysqld_stmt_prepare(THD *thd, const Prepared_statement *stmt; bool error; DBUG_ENTER("mysqld_stmt_prepare"); - DBUG_PRINT("prep_query", ("%s", packet)); /* First of all clear possible warnings from the previous command */ - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, opt_userstat_running); if (! (stmt= new Prepared_statement(thd))) - DBUG_VOID_RETURN; /* out of memory: error is set in Sql_alloc */ + goto end; /* out of memory: error is set in Sql_alloc */ if (thd->stmt_map.insert(thd, stmt)) { @@ -2082,7 +2081,7 @@ void mysqld_stmt_prepare(THD *thd, const The error is set in the insert. The statement itself will be also deleted there (this is how the hash works). */ - DBUG_VOID_RETURN; + goto end; } /* Reset warnings from previous command */ @@ -2109,6 +2108,7 @@ void mysqld_stmt_prepare(THD *thd, const thd->protocol= save_protocol; /* check_prepared_statemnt sends the metadata packet in case of success */ +end: DBUG_VOID_RETURN; } @@ -2450,7 +2450,7 @@ void mysqld_stmt_execute(THD *thd, char packet+= 9; /* stmt_id + 5 bytes of flags */ /* First of all clear possible warnings from the previous command */ - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, opt_userstat_running); if (!(stmt= find_prepared_statement(thd, stmt_id))) { @@ -2549,7 +2549,8 @@ void mysqld_stmt_fetch(THD *thd, char *p DBUG_ENTER("mysqld_stmt_fetch"); /* First of all clear possible warnings from the previous command */ - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, opt_userstat_running); + status_var_increment(thd->status_var.com_stmt_fetch); if (!(stmt= find_prepared_statement(thd, stmt_id))) { @@ -2615,7 +2616,7 @@ void mysqld_stmt_reset(THD *thd, char *p DBUG_ENTER("mysqld_stmt_reset"); /* First of all clear possible warnings from the previous command */ - mysql_reset_thd_for_next_command(thd); + mysql_reset_thd_for_next_command(thd, opt_userstat_running); status_var_increment(thd->status_var.com_stmt_reset); if (!(stmt= find_prepared_statement(thd, stmt_id))) === modified file 'sql/sql_select.cc' --- a/sql/sql_select.cc 2009-09-15 10:46:35 +0000 +++ b/sql/sql_select.cc 2009-10-19 17:14:48 +0000 @@ -10603,8 +10603,9 @@ error: static bool open_tmp_table(TABLE *table) { int error; - if ((error=table->file->ha_open(table, table->s->table_name.str,O_RDWR, - HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE))) + if ((error= table->file->ha_open(table, table->s->table_name.str, O_RDWR, + HA_OPEN_TMP_TABLE | + HA_OPEN_INTERNAL_TABLE))) { table->file->print_error(error,MYF(0)); /* purecov: inspected */ table->db_stat=0; @@ -10949,7 +10950,7 @@ create_internal_tmp_table_from_heap2(THD is safe as this is a temporary MyISAM table without timestamp/autoincrement or partitioning. */ - while (!table->file->rnd_next(new_table.record[1])) + while (!table->file->ha_rnd_next(new_table.record[1])) { write_err= new_table.file->ha_write_row(new_table.record[1]); DBUG_EXECUTE_IF("raise_error", write_err= HA_ERR_FOUND_DUPP_KEY ;); @@ -11746,10 +11747,10 @@ int safe_index_read(JOIN_TAB *tab) { int error; TABLE *table= tab->table; - if ((error=table->file->index_read_map(table->record[0], - tab->ref.key_buff, - make_prev_keypart_map(tab->ref.key_parts), - HA_READ_KEY_EXACT))) + if ((error= table->file->ha_index_read_map(table->record[0], + tab->ref.key_buff, + make_prev_keypart_map(tab->ref.key_parts), + HA_READ_KEY_EXACT))) return report_error(table, error); return 0; } @@ -11858,8 +11859,8 @@ join_read_system(JOIN_TAB *tab) int error; if (table->status & STATUS_GARBAGE) // If first read { - if ((error=table->file->read_first_row(table->record[0], - table->s->primary_key))) + if ((error= table->file->ha_read_first_row(table->record[0], + table->s->primary_key))) { if (error != HA_ERR_END_OF_FILE) return report_error(table, error); @@ -11901,10 +11902,10 @@ join_read_const(JOIN_TAB *tab) error=HA_ERR_KEY_NOT_FOUND; else { - error=table->file->index_read_idx_map(table->record[0],tab->ref.key, - (uchar*) tab->ref.key_buff, - make_prev_keypart_map(tab->ref.key_parts), - HA_READ_KEY_EXACT); + error= table->file->ha_index_read_idx_map(table->record[0],tab->ref.key, + (uchar*) tab->ref.key_buff, + make_prev_keypart_map(tab->ref.key_parts), + HA_READ_KEY_EXACT); } if (error) { @@ -11949,10 +11950,10 @@ join_read_key(JOIN_TAB *tab) table->status=STATUS_NOT_FOUND; return -1; } - error=table->file->index_read_map(table->record[0], - tab->ref.key_buff, - make_prev_keypart_map(tab->ref.key_parts), - HA_READ_KEY_EXACT); + error= table->file->ha_index_read_map(table->record[0], + tab->ref.key_buff, + make_prev_keypart_map(tab->ref.key_parts), + HA_READ_KEY_EXACT); if (error && error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) return report_error(table, error); } @@ -12005,10 +12006,10 @@ join_read_always_key(JOIN_TAB *tab) if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref)) return -1; - if ((error=table->file->index_read_map(table->record[0], - tab->ref.key_buff, - make_prev_keypart_map(tab->ref.key_parts), - HA_READ_KEY_EXACT))) + if ((error= table->file->ha_index_read_map(table->record[0], + tab->ref.key_buff, + make_prev_keypart_map(tab->ref.key_parts), + HA_READ_KEY_EXACT))) { if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) return report_error(table, error); @@ -12039,9 +12040,9 @@ join_read_last_key(JOIN_TAB *tab) } if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref)) return -1; - if ((error=table->file->index_read_last_map(table->record[0], - tab->ref.key_buff, - make_prev_keypart_map(tab->ref.key_parts)))) + if ((error= table->file->ha_index_read_last_map(table->record[0], + tab->ref.key_buff, + make_prev_keypart_map(tab->ref.key_parts)))) { if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) return report_error(table, error); @@ -12066,9 +12067,9 @@ join_read_next_same(READ_RECORD *info) TABLE *table= info->table; JOIN_TAB *tab=table->reginfo.join_tab; - if ((error=table->file->index_next_same(table->record[0], - tab->ref.key_buff, - tab->ref.key_length))) + if ((error= table->file->ha_index_next_same(table->record[0], + tab->ref.key_buff, + tab->ref.key_length))) { if (error != HA_ERR_END_OF_FILE) return report_error(table, error); @@ -12086,7 +12087,7 @@ join_read_prev_same(READ_RECORD *info) TABLE *table= info->table; JOIN_TAB *tab=table->reginfo.join_tab; - if ((error=table->file->index_prev(table->record[0]))) + if ((error= table->file->ha_index_prev(table->record[0]))) return report_error(table, error); if (key_cmp_if_same(table, tab->ref.key_buff, tab->ref.key, tab->ref.key_length)) @@ -12158,7 +12159,7 @@ join_read_first(JOIN_TAB *tab) error= table->file->ha_index_init(tab->index, tab->sorted); if (!error) error= table->file->prepare_index_scan(); - if (error || (error=tab->table->file->index_first(tab->table->record[0]))) + if (error || (error=tab->table->file->ha_index_first(tab->table->record[0]))) { if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) report_error(table, error); @@ -12172,7 +12173,7 @@ static int join_read_next(READ_RECORD *info) { int error; - if ((error=info->file->index_next(info->record))) + if ((error= info->file->ha_index_next(info->record))) return report_error(info->table, error); return 0; } @@ -12199,7 +12200,7 @@ join_read_last(JOIN_TAB *tab) error= table->file->ha_index_init(tab->index, 1); if (!error) error= table->file->prepare_index_scan(); - if (error || (error= tab->table->file->index_last(tab->table->record[0]))) + if (error || (error= tab->table->file->ha_index_last(tab->table->record[0]))) return report_error(table, error); return 0; } @@ -12209,7 +12210,7 @@ static int join_read_prev(READ_RECORD *info) { int error; - if ((error= info->file->index_prev(info->record))) + if ((error= info->file->ha_index_prev(info->record))) return report_error(info->table, error); return 0; } @@ -12234,7 +12235,7 @@ join_ft_read_first(JOIN_TAB *tab) #endif table->file->ft_init(); - if ((error= table->file->ft_read(table->record[0]))) + if ((error= table->file->ha_ft_read(table->record[0]))) return report_error(table, error); return 0; } @@ -12243,7 +12244,7 @@ static int join_ft_read_next(READ_RECORD *info) { int error; - if ((error= info->file->ft_read(info->table->record[0]))) + if ((error= info->file->ha_ft_read(info->table->record[0]))) return report_error(info->table, error); return 0; } @@ -12535,7 +12536,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab { int error; join->found_records++; - if ((error=table->file->ha_write_row(table->record[0]))) + if ((error= table->file->ha_write_row(table->record[0]))) { if (!table->file->is_fatal_error(error, HA_CHECK_DUP)) goto end; @@ -12590,15 +12591,15 @@ end_update(JOIN *join, JOIN_TAB *join_ta if (item->maybe_null) group->buff[-1]= (char) group->field->is_null(); } - if (!table->file->index_read_map(table->record[1], - join->tmp_table_param.group_buff, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + if (!table->file->ha_index_read_map(table->record[1], + join->tmp_table_param.group_buff, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) { /* Update old record */ restore_record(table,record[1]); update_tmptable_sum_func(join->sum_funcs,table); - if ((error=table->file->ha_update_row(table->record[1], - table->record[0]))) + if ((error= table->file->ha_update_row(table->record[1], + table->record[0]))) { table->file->print_error(error,MYF(0)); /* purecov: inspected */ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ @@ -12621,7 +12622,7 @@ end_update(JOIN *join, JOIN_TAB *join_ta } init_tmptable_sum_functions(join->sum_funcs); copy_funcs(join->tmp_table_param.items_to_copy); - if ((error=table->file->ha_write_row(table->record[0]))) + if ((error= table->file->ha_write_row(table->record[0]))) { if (create_internal_tmp_table_from_heap(join->thd, table, &join->tmp_table_param, @@ -12662,7 +12663,7 @@ end_unique_update(JOIN *join, JOIN_TAB * copy_fields(&join->tmp_table_param); // Groups are copied twice. copy_funcs(join->tmp_table_param.items_to_copy); - if (!(error=table->file->ha_write_row(table->record[0]))) + if (!(error= table->file->ha_write_row(table->record[0]))) join->send_records++; // New group else { @@ -12671,15 +12672,15 @@ end_unique_update(JOIN *join, JOIN_TAB * table->file->print_error(error,MYF(0)); /* purecov: inspected */ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ } - if (table->file->rnd_pos(table->record[1],table->file->dup_ref)) + if (table->file->ha_rnd_pos(table->record[1],table->file->dup_ref)) { table->file->print_error(error,MYF(0)); /* purecov: inspected */ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ } restore_record(table,record[1]); update_tmptable_sum_func(join->sum_funcs,table); - if ((error=table->file->ha_update_row(table->record[1], - table->record[0]))) + if ((error= table->file->ha_update_row(table->record[1], + table->record[0]))) { table->file->print_error(error,MYF(0)); /* purecov: inspected */ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ @@ -14016,7 +14017,7 @@ static int remove_dup_with_compare(THD * new_record=(char*) table->record[1]+offset; file->ha_rnd_init(1); - error=file->rnd_next(record); + error= file->ha_rnd_next(record); for (;;) { if (thd->killed) @@ -14035,9 +14036,9 @@ static int remove_dup_with_compare(THD * } if (having && !having->val_int()) { - if ((error=file->ha_delete_row(record))) + if ((error= file->ha_delete_row(record))) goto err; - error=file->rnd_next(record); + error= file->ha_rnd_next(record); continue; } if (copy_blobs(first_field)) @@ -14052,7 +14053,7 @@ static int remove_dup_with_compare(THD * bool found=0; for (;;) { - if ((error=file->rnd_next(record))) + if ((error= file->ha_rnd_next(record))) { if (error == HA_ERR_RECORD_DELETED) continue; @@ -14062,7 +14063,7 @@ static int remove_dup_with_compare(THD * } if (compare_record(table, first_field) == 0) { - if ((error=file->ha_delete_row(record))) + if ((error= file->ha_delete_row(record))) goto err; } else if (!found) @@ -14152,7 +14153,7 @@ static int remove_dup_with_hash_index(TH error=0; goto err; } - if ((error=file->rnd_next(record))) + if ((error= file->ha_rnd_next(record))) { if (error == HA_ERR_RECORD_DELETED) continue; @@ -14162,7 +14163,7 @@ static int remove_dup_with_hash_index(TH } if (having && !having->val_int()) { - if ((error=file->ha_delete_row(record))) + if ((error= file->ha_delete_row(record))) goto err; continue; } @@ -14179,7 +14180,7 @@ static int remove_dup_with_hash_index(TH if (hash_search(&hash, org_key_pos, key_length)) { /* Duplicated found ; Remove the row */ - if ((error=file->ha_delete_row(record))) + if ((error= file->ha_delete_row(record))) goto err; } else === modified file 'sql/sql_servers.cc' --- a/sql/sql_servers.cc 2009-03-20 14:27:53 +0000 +++ b/sql/sql_servers.cc 2009-10-19 17:14:48 +0000 @@ -520,10 +520,10 @@ int insert_server_record(TABLE *table, F system_charset_info); /* read index until record is that specified in server_name */ - if ((error= table->file->index_read_idx_map(table->record[0], 0, - (uchar *)table->field[0]->ptr, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT))) + if ((error= table->file->ha_index_read_idx_map(table->record[0], 0, + (uchar *)table->field[0]->ptr, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT))) { /* if not found, err */ if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) @@ -863,10 +863,10 @@ update_server_record(TABLE *table, FOREI server->server_name_length, system_charset_info); - if ((error= table->file->index_read_idx_map(table->record[0], 0, - (uchar *)table->field[0]->ptr, - ~(longlong)0, - HA_READ_KEY_EXACT))) + if ((error= table->file->ha_index_read_idx_map(table->record[0], 0, + (uchar *)table->field[0]->ptr, + ~(longlong)0, + HA_READ_KEY_EXACT))) { if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) table->file->print_error(error, MYF(0)); @@ -920,10 +920,10 @@ delete_server_record(TABLE *table, /* set the field that's the PK to the value we're looking for */ table->field[0]->store(server_name, server_name_length, system_charset_info); - if ((error= table->file->index_read_idx_map(table->record[0], 0, - (uchar *)table->field[0]->ptr, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT))) + if ((error= table->file->ha_index_read_idx_map(table->record[0], 0, + (uchar *)table->field[0]->ptr, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT))) { if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) table->file->print_error(error, MYF(0)); === modified file 'sql/sql_show.cc' --- a/sql/sql_show.cc 2009-09-23 11:03:47 +0000 +++ b/sql/sql_show.cc 2009-10-19 17:14:48 +0000 @@ -714,6 +714,7 @@ bool mysqld_show_create_db(THD *thd, cha sctx->master_access); if (!(db_access & DB_ACLS) && check_grant_db(thd,dbname)) { + status_var_increment(thd->status_var.access_denied_errors); my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), sctx->priv_user, sctx->host_or_ip, dbname); general_log_print(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), @@ -2100,11 +2101,6 @@ void remove_status_vars(SHOW_VAR *list) } } -inline void make_upper(char *buf) -{ - for (; *buf; buf++) - *buf= my_toupper(system_charset_info, *buf); -} static bool show_status_array(THD *thd, const char *wild, SHOW_VAR *variables, @@ -2143,7 +2139,7 @@ static bool show_status_array(THD *thd, strnmov(prefix_end, variables->name, len); name_buffer[sizeof(name_buffer)-1]=0; /* Safety */ if (ucase_names) - make_upper(name_buffer); + my_caseup_str(system_charset_info, name_buffer); restore_record(table, s->default_values); table->field[0]->store(name_buffer, strlen(name_buffer), @@ -2270,6 +2266,323 @@ end: DBUG_RETURN(res); } +#ifdef COMPLEAT_PATCH_NOT_ADDED_YET +/* + Aggregate values for mapped_user entries by their role. + + SYNOPSIS + aggregate_user_stats + all_user_stats - input to aggregate + agg_user_stats - returns aggregated values + + RETURN + 0 - OK + 1 - error +*/ + +static int aggregate_user_stats(HASH *all_user_stats, HASH *agg_user_stats) +{ + DBUG_ENTER("aggregate_user_stats"); + if (hash_init(agg_user_stats, system_charset_info, + max(all_user_stats->records, 1), + 0, 0, (hash_get_key)get_key_user_stats, + (hash_free_key)free_user_stats, 0)) + { + sql_print_error("Malloc in aggregate_user_stats failed"); + DBUG_RETURN(1); + } + + for (uint i= 0; i < all_user_stats->records; i++) + { + USER_STATS *user= (USER_STATS*)hash_element(all_user_stats, i); + USER_STATS *agg_user; + uint name_length= strlen(user->priv_user); + + if (!(agg_user= (USER_STATS*) hash_search(agg_user_stats, + (uchar*)user->priv_user, + name_length))) + { + // First entry for this role. + if (!(agg_user= (USER_STATS*) my_malloc(sizeof(USER_STATS), + MYF(MY_WME | MY_ZEROFILL)))) + { + sql_print_error("Malloc in aggregate_user_stats failed"); + DBUG_RETURN(1); + } + + init_user_stats(agg_user, user->priv_user, name_length, + user->priv_user, + user->total_connections, user->concurrent_connections, + user->connected_time, user->busy_time, user->cpu_time, + user->bytes_received, user->bytes_sent, + user->binlog_bytes_written, + user->rows_sent, user->rows_read, + user->rows_inserted, user->rows_deleted, + user->rows_updated, + user->select_commands, user->update_commands, + user->other_commands, + user->commit_trans, user->rollback_trans, + user->denied_connections, user->lost_connections, + user->access_denied_errors, user->empty_queries); + + if (my_hash_insert(agg_user_stats, (uchar*) agg_user)) + { + /* Out of memory */ + my_free(agg_user, 0); + sql_print_error("Malloc in aggregate_user_stats failed"); + DBUG_RETURN(1); + } + } + else + { + /* Aggregate with existing values for this role. */ + add_user_stats(agg_user, + user->total_connections, user->concurrent_connections, + user->connected_time, user->busy_time, user->cpu_time, + user->bytes_received, user->bytes_sent, + user->binlog_bytes_written, + user->rows_sent, user->rows_read, + user->rows_inserted, user->rows_deleted, + user->rows_updated, + user->select_commands, user->update_commands, + user->other_commands, + user->commit_trans, user->rollback_trans, + user->denied_connections, user->lost_connections, + user->access_denied_errors, user->empty_queries); + } + } + DBUG_PRINT("exit", ("aggregated %lu input into %lu output entries", + all_user_stats->records, agg_user_stats->records)); + DBUG_RETURN(0); +} +#endif + +/* + Write result to network for SHOW USER_STATISTICS + + SYNOPSIS + send_user_stats + all_user_stats - values to return + table - I_S table + + RETURN + 0 - OK + 1 - error +*/ + +int send_user_stats(THD* thd, HASH *all_user_stats, TABLE *table) +{ + DBUG_ENTER("send_user_stats"); + + for (uint i= 0; i < all_user_stats->records; i++) + { + uint j= 0; + USER_STATS *user_stats= (USER_STATS*) hash_element(all_user_stats, i); + + table->field[j++]->store(user_stats->user, user_stats->user_name_length, + system_charset_info); + table->field[j++]->store((longlong)user_stats->total_connections,TRUE); + table->field[j++]->store((longlong)user_stats->concurrent_connections); + table->field[j++]->store((longlong)user_stats->connected_time); + table->field[j++]->store((double)user_stats->busy_time); + table->field[j++]->store((double)user_stats->cpu_time); + table->field[j++]->store((longlong)user_stats->bytes_received, TRUE); + table->field[j++]->store((longlong)user_stats->bytes_sent, TRUE); + table->field[j++]->store((longlong)user_stats->binlog_bytes_written, TRUE); + table->field[j++]->store((longlong)user_stats->rows_read, TRUE); + table->field[j++]->store((longlong)user_stats->rows_sent, TRUE); + table->field[j++]->store((longlong)user_stats->rows_deleted, TRUE); + table->field[j++]->store((longlong)user_stats->rows_inserted, TRUE); + table->field[j++]->store((longlong)user_stats->rows_updated, TRUE); + table->field[j++]->store((longlong)user_stats->select_commands, TRUE); + table->field[j++]->store((longlong)user_stats->update_commands, TRUE); + table->field[j++]->store((longlong)user_stats->other_commands, TRUE); + table->field[j++]->store((longlong)user_stats->commit_trans, TRUE); + table->field[j++]->store((longlong)user_stats->rollback_trans, TRUE); + table->field[j++]->store((longlong)user_stats->denied_connections, TRUE); + table->field[j++]->store((longlong)user_stats->lost_connections, TRUE); + table->field[j++]->store((longlong)user_stats->access_denied_errors, TRUE); + table->field[j++]->store((longlong)user_stats->empty_queries, TRUE); + if (schema_table_store_record(thd, table)) + { + DBUG_PRINT("error", ("store record error")); + DBUG_RETURN(1); + } + } + DBUG_RETURN(0); +} + +/* + Process SHOW USER_STATISTICS + + SYNOPSIS + mysqld_show_user_stats + thd - current thread + wild - limit results to the entry for this user + with_roles - when true, display role for mapped users + + RETURN + 0 - OK + 1 - error +*/ + +int fill_schema_user_stats(THD* thd, TABLE_LIST* tables, COND* cond) +{ + TABLE *table= tables->table; + int result; + DBUG_ENTER("fill_schema_user_stats"); + + if (check_global_access(thd, SUPER_ACL | PROCESS_ACL)) + DBUG_RETURN(1); + + /* + Iterates through all the global stats and sends them to the client. + Pattern matching on the client IP is supported. + */ + + pthread_mutex_lock(&LOCK_global_user_client_stats); + result= send_user_stats(thd, &global_user_stats, table) != 0; + pthread_mutex_unlock(&LOCK_global_user_client_stats); + + DBUG_PRINT("exit", ("result: %d", result)); + DBUG_RETURN(result); +} + +/* + Process SHOW CLIENT_STATISTICS + + SYNOPSIS + mysqld_show_client_stats + thd - current thread + wild - limit results to the entry for this client + + RETURN + 0 - OK + 1 - error +*/ + +int fill_schema_client_stats(THD* thd, TABLE_LIST* tables, COND* cond) +{ + TABLE *table= tables->table; + int result; + DBUG_ENTER("fill_schema_client_stats"); + + if (check_global_access(thd, SUPER_ACL | PROCESS_ACL)) + DBUG_RETURN(1); + + /* + Iterates through all the global stats and sends them to the client. + Pattern matching on the client IP is supported. + */ + + pthread_mutex_lock(&LOCK_global_user_client_stats); + result= send_user_stats(thd, &global_client_stats, table) != 0; + pthread_mutex_unlock(&LOCK_global_user_client_stats); + + DBUG_PRINT("exit", ("result: %d", result)); + DBUG_RETURN(result); +} + + +/* Fill information schema table with table statistics */ + +int fill_schema_table_stats(THD *thd, TABLE_LIST *tables, COND *cond) +{ + TABLE *table= tables->table; + DBUG_ENTER("fill_schema_table_stats"); + + pthread_mutex_lock(&LOCK_global_table_stats); + for (uint i= 0; i < global_table_stats.records; i++) + { + char *end_of_schema; + TABLE_STATS *table_stats= + (TABLE_STATS*)hash_element(&global_table_stats, i); + TABLE_LIST tmp_table; + size_t schema_length, table_name_length; + + end_of_schema= strend(table_stats->table); + schema_length= (size_t) (end_of_schema - table_stats->table); + table_name_length= strlen(table_stats->table + schema_length + 1); + + bzero((char*) &tmp_table,sizeof(tmp_table)); + tmp_table.db= table_stats->table; + tmp_table.table_name= end_of_schema+1; + tmp_table.grant.privilege= 0; + if (check_access(thd, SELECT_ACL | EXTRA_ACL, tmp_table.db, + &tmp_table.grant.privilege, 0, 0, + is_schema_db(tmp_table.db)) || + check_grant(thd, SELECT_ACL, &tmp_table, 1, UINT_MAX, + 1)) + continue; + + table->field[0]->store(table_stats->table, schema_length, + system_charset_info); + table->field[1]->store(table_stats->table + schema_length+1, + table_name_length, system_charset_info); + table->field[2]->store((longlong)table_stats->rows_read, TRUE); + table->field[3]->store((longlong)table_stats->rows_changed, TRUE); + table->field[4]->store((longlong)table_stats->rows_changed_x_indexes, + TRUE); + if (schema_table_store_record(thd, table)) + { + VOID(pthread_mutex_unlock(&LOCK_global_table_stats)); + DBUG_RETURN(1); + } + } + pthread_mutex_unlock(&LOCK_global_table_stats); + DBUG_RETURN(0); +} + + +/* Fill information schema table with index statistics */ + +int fill_schema_index_stats(THD *thd, TABLE_LIST *tables, COND *cond) +{ + TABLE *table= tables->table; + DBUG_ENTER("fill_schema_index_stats"); + + pthread_mutex_lock(&LOCK_global_index_stats); + for (uint i= 0; i < global_index_stats.records; i++) + { + INDEX_STATS *index_stats = + (INDEX_STATS*) hash_element(&global_index_stats, i); + TABLE_LIST tmp_table; + char *index_name; + size_t schema_name_length, table_name_length, index_name_length; + + bzero((char*) &tmp_table,sizeof(tmp_table)); + tmp_table.db= index_stats->index; + tmp_table.table_name= strend(index_stats->index)+1; + tmp_table.grant.privilege= 0; + if (check_access(thd, SELECT_ACL | EXTRA_ACL, tmp_table.db, + &tmp_table.grant.privilege, 0, 0, + is_schema_db(tmp_table.db)) || + check_grant(thd, SELECT_ACL, &tmp_table, 1, UINT_MAX, 1)) + continue; + + index_name= strend(tmp_table.table_name)+1; + schema_name_length= (tmp_table.table_name - index_stats->index) -1; + table_name_length= (index_name - tmp_table.table_name)-1; + index_name_length= (index_stats->index_name_length - schema_name_length - + table_name_length - 3); + + table->field[0]->store(tmp_table.db, schema_name_length, + system_charset_info); + table->field[1]->store(tmp_table.table_name, table_name_length, + system_charset_info); + table->field[2]->store(index_name, index_name_length, system_charset_info); + table->field[3]->store((longlong)index_stats->rows_read, TRUE); + + if (schema_table_store_record(thd, table)) + { + VOID(pthread_mutex_unlock(&LOCK_global_index_stats)); + DBUG_RETURN(1); + } + } + pthread_mutex_unlock(&LOCK_global_index_stats); + DBUG_RETURN(0); +} + /* collect status for all running threads */ @@ -4206,7 +4519,7 @@ int fill_schema_proc(THD *thd, TABLE_LIS DBUG_RETURN(1); } proc_table->file->ha_index_init(0, 1); - if ((res= proc_table->file->index_first(proc_table->record[0]))) + if ((res= proc_table->file->ha_index_first(proc_table->record[0]))) { res= (res == HA_ERR_END_OF_FILE) ? 0 : 1; goto err; @@ -4216,7 +4529,7 @@ int fill_schema_proc(THD *thd, TABLE_LIS res= 1; goto err; } - while (!proc_table->file->index_next(proc_table->record[0])) + while (!proc_table->file->ha_index_next(proc_table->record[0])) { if (store_schema_proc(thd, table, proc_table, wild, full_access, definer)) { @@ -5462,6 +5775,81 @@ struct schema_table_ref ST_SCHEMA_TABLE *schema_table; }; +ST_FIELD_INFO user_stats_fields_info[]= +{ + {"USER", USERNAME_LENGTH, MYSQL_TYPE_STRING, 0, 0, "User", SKIP_OPEN_TABLE}, + {"TOTAL_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Total_connections",SKIP_OPEN_TABLE}, + {"CONCURRENT_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Concurrent_connections",SKIP_OPEN_TABLE}, + {"CONNECTED_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Connected_time",SKIP_OPEN_TABLE}, + {"BUSY_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_DOUBLE, 0, 0, "Busy_time",SKIP_OPEN_TABLE}, + {"CPU_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_DOUBLE, 0, 0, "Cpu_time",SKIP_OPEN_TABLE}, + {"BYTES_RECEIVED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Bytes_received",SKIP_OPEN_TABLE}, + {"BYTES_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Bytes_sent",SKIP_OPEN_TABLE}, + {"BINLOG_BYTES_WRITTEN", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Binlog_bytes_written",SKIP_OPEN_TABLE}, + {"ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_read",SKIP_OPEN_TABLE}, + {"ROWS_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_sent",SKIP_OPEN_TABLE}, + {"ROWS_DELETED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_deleted",SKIP_OPEN_TABLE}, + {"ROWS_INSERTED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_inserted",SKIP_OPEN_TABLE}, + {"ROWS_UPDATED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_updated",SKIP_OPEN_TABLE}, + {"SELECT_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Select_commands",SKIP_OPEN_TABLE}, + {"UPDATE_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Update_commands",SKIP_OPEN_TABLE}, + {"OTHER_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Other_commands",SKIP_OPEN_TABLE}, + {"COMMIT_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Commit_transactions",SKIP_OPEN_TABLE}, + {"ROLLBACK_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rollback_transactions",SKIP_OPEN_TABLE}, + {"DENIED_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Denied_connections",SKIP_OPEN_TABLE}, + {"LOST_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Lost_connections",SKIP_OPEN_TABLE}, + {"ACCESS_DENIED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Access_denied",SKIP_OPEN_TABLE}, + {"EMPTY_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Empty_queries",SKIP_OPEN_TABLE}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} +}; + +ST_FIELD_INFO client_stats_fields_info[]= +{ + {"CLIENT", LIST_PROCESS_HOST_LEN, MYSQL_TYPE_STRING, 0, 0, "Client",SKIP_OPEN_TABLE}, + {"TOTAL_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Total_connections",SKIP_OPEN_TABLE}, + {"CONCURRENT_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Concurrent_connections",SKIP_OPEN_TABLE}, + {"CONNECTED_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Connected_time",SKIP_OPEN_TABLE}, + {"BUSY_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_DOUBLE, 0, 0, "Busy_time",SKIP_OPEN_TABLE}, + {"CPU_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_DOUBLE, 0, 0, "Cpu_time",SKIP_OPEN_TABLE}, + {"BYTES_RECEIVED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Bytes_received",SKIP_OPEN_TABLE}, + {"BYTES_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Bytes_sent",SKIP_OPEN_TABLE}, + {"BINLOG_BYTES_WRITTEN", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Binlog_bytes_written",SKIP_OPEN_TABLE}, + {"ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_read",SKIP_OPEN_TABLE}, + {"ROWS_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_sent",SKIP_OPEN_TABLE}, + {"ROWS_DELETED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_deleted",SKIP_OPEN_TABLE}, + {"ROWS_INSERTED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_inserted",SKIP_OPEN_TABLE}, + {"ROWS_UPDATED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_updated",SKIP_OPEN_TABLE}, + {"SELECT_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Select_commands",SKIP_OPEN_TABLE}, + {"UPDATE_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Update_commands",SKIP_OPEN_TABLE}, + {"OTHER_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Other_commands",SKIP_OPEN_TABLE}, + {"COMMIT_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Commit_transactions",SKIP_OPEN_TABLE}, + {"ROLLBACK_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rollback_transactions",SKIP_OPEN_TABLE}, + {"DENIED_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Denied_connections",SKIP_OPEN_TABLE}, + {"LOST_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Lost_connections",SKIP_OPEN_TABLE}, + {"ACCESS_DENIED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Access_denied",SKIP_OPEN_TABLE}, + {"EMPTY_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Empty_queries",SKIP_OPEN_TABLE}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} +}; + + +ST_FIELD_INFO table_stats_fields_info[]= +{ + {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_schema",SKIP_OPEN_TABLE}, + {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_name",SKIP_OPEN_TABLE}, + {"ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_read",SKIP_OPEN_TABLE}, + {"ROWS_CHANGED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_changed",SKIP_OPEN_TABLE}, + {"ROWS_CHANGED_X_INDEXES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_changed_x_#indexes",SKIP_OPEN_TABLE}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} +}; + +ST_FIELD_INFO index_stats_fields_info[]= +{ + {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_schema",SKIP_OPEN_TABLE}, + {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_name",SKIP_OPEN_TABLE}, + {"INDEX_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Index_name",SKIP_OPEN_TABLE}, + {"ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_read",SKIP_OPEN_TABLE}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0,0} +}; /* Find schema_tables elment by name @@ -6683,6 +7071,8 @@ ST_SCHEMA_TABLE schema_tables[]= { {"CHARACTER_SETS", charsets_fields_info, create_schema_table, fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0}, + {"CLIENT_STATISTICS", client_stats_fields_info, create_schema_table, + fill_schema_client_stats, make_old_format, 0, -1, -1, 0, 0}, {"COLLATIONS", collation_fields_info, create_schema_table, fill_schema_collation, make_old_format, 0, -1, -1, 0, 0}, {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info, @@ -6707,6 +7097,8 @@ ST_SCHEMA_TABLE schema_tables[]= fill_status, make_old_format, 0, 0, -1, 0, 0}, {"GLOBAL_VARIABLES", variables_fields_info, create_schema_table, fill_variables, make_old_format, 0, 0, -1, 0, 0}, + {"INDEX_STATISTICS", index_stats_fields_info, create_schema_table, + fill_schema_index_stats, make_old_format, 0, -1, -1, 0, 0}, {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table, get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0, OPEN_TABLE_ONLY}, @@ -6748,11 +7140,15 @@ ST_SCHEMA_TABLE schema_tables[]= get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0}, {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table, fill_schema_table_privileges, 0, 0, -1, -1, 0, 0}, + {"TABLE_STATISTICS", table_stats_fields_info, create_schema_table, + fill_schema_table_stats, make_old_format, 0, -1, -1, 0, 0}, {"TRIGGERS", triggers_fields_info, create_schema_table, get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0, OPEN_TABLE_ONLY}, {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table, fill_schema_user_privileges, 0, 0, -1, -1, 0, 0}, + {"USER_STATISTICS", user_stats_fields_info, create_schema_table, + fill_schema_user_stats, make_old_format, 0, -1, -1, 0, 0}, {"VARIABLES", variables_fields_info, create_schema_table, fill_variables, make_old_format, 0, 0, -1, 1, 0}, {"VIEWS", view_fields_info, create_schema_table, === modified file 'sql/sql_table.cc' --- a/sql/sql_table.cc 2009-09-18 01:04:43 +0000 +++ b/sql/sql_table.cc 2009-10-19 17:14:48 +0000 @@ -7815,7 +7815,7 @@ bool mysql_checksum_table(THD *thd, TABL goto err; } ha_checksum row_crc= 0; - int error= t->file->rnd_next(t->record[0]); + int error= t->file->ha_rnd_next(t->record[0]); if (unlikely(error)) { if (error == HA_ERR_RECORD_DELETED) === modified file 'sql/sql_udf.cc' --- a/sql/sql_udf.cc 2009-05-15 12:57:51 +0000 +++ b/sql/sql_udf.cc 2009-10-19 17:14:48 +0000 @@ -567,10 +567,10 @@ int mysql_drop_function(THD *thd,const L goto err; table->use_all_columns(); table->field[0]->store(exact_name_str, exact_name_len, &my_charset_bin); - if (!table->file->index_read_idx_map(table->record[0], 0, - (uchar*) table->field[0]->ptr, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + if (!table->file->ha_index_read_idx_map(table->record[0], 0, + (uchar*) table->field[0]->ptr, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) { int error; if ((error = table->file->ha_delete_row(table->record[0]))) === modified file 'sql/sql_update.cc' --- a/sql/sql_update.cc 2009-09-07 20:50:10 +0000 +++ b/sql/sql_update.cc 2009-10-19 17:14:48 +0000 @@ -142,7 +142,7 @@ static void prepare_record_for_error_mes /* Tell the engine about the new set. */ table->file->column_bitmaps_signal(); /* Read record that is identified by table->file->ref. */ - (void) table->file->rnd_pos(table->record[1], table->file->ref); + (void) table->file->ha_rnd_pos(table->record[1], table->file->ref); /* Copy the newly read columns into the new record. */ for (field_p= table->field; (field= *field_p); field_p++) if (bitmap_is_set(&unique_map, field->field_index)) @@ -1928,7 +1928,7 @@ int multi_update::do_updates() { if (thd->killed && trans_safe) goto err; - if ((local_error=tmp_table->file->rnd_next(tmp_table->record[0]))) + if ((local_error= tmp_table->file->ha_rnd_next(tmp_table->record[0]))) { if (local_error == HA_ERR_END_OF_FILE) break; @@ -1943,12 +1943,12 @@ int multi_update::do_updates() uint field_num= 0; do { - if((local_error= - tbl->file->rnd_pos(tbl->record[0], - (uchar *) tmp_table->field[field_num]->ptr))) + if ((local_error= + tbl->file->ha_rnd_pos(tbl->record[0], + (uchar*) tmp_table->field[field_num]->ptr))) goto err; field_num++; - } while((tbl= check_opt_it++)); + } while ((tbl= check_opt_it++)); table->status|= STATUS_UPDATED; store_record(table,record[1]); === modified file 'sql/sql_yacc.yy' --- a/sql/sql_yacc.yy 2009-09-07 20:50:10 +0000 +++ b/sql/sql_yacc.yy 2009-10-19 17:14:48 +0000 @@ -598,6 +598,7 @@ bool my_yyoverflow(short **a, YYSTYPE ** %token CHECK_SYM /* SQL-2003-R */ %token CIPHER_SYM %token CLIENT_SYM +%token CLIENT_STATS_SYM %token CLOSE_SYM /* SQL-2003-R */ %token COALESCE /* SQL-2003-N */ %token CODE_SYM @@ -744,6 +745,7 @@ bool my_yyoverflow(short **a, YYSTYPE ** %token IMPORT %token INDEXES %token INDEX_SYM +%token INDEX_STATS_SYM %token INFILE %token INITIAL_SIZE_SYM %token INNER_SYM /* SQL-2003-R */ @@ -985,6 +987,7 @@ bool my_yyoverflow(short **a, YYSTYPE ** %token SIGNED_SYM %token SIMPLE_SYM /* SQL-2003-N */ %token SLAVE +%token SLOW_SYM %token SMALLINT /* SQL-2003-R */ %token SNAPSHOT_SYM %token SOCKET_SYM @@ -1029,6 +1032,7 @@ bool my_yyoverflow(short **a, YYSTYPE ** %token TABLES %token TABLESPACE %token TABLE_REF_PRIORITY +%token TABLE_STATS_SYM %token TABLE_SYM /* SQL-2003-R */ %token TABLE_CHECKSUM_SYM %token TEMPORARY /* SQL-2003-N */ @@ -1076,6 +1080,7 @@ bool my_yyoverflow(short **a, YYSTYPE ** %token UPGRADE_SYM %token USAGE /* SQL-2003-N */ %token USER /* SQL-2003-R */ +%token USER_STATS_SYM %token USE_FRM %token USE_SYM %token USING /* SQL-2003-R */ @@ -10131,6 +10136,34 @@ show_param: { Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT; } + | CLIENT_STATS_SYM + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_SHOW_CLIENT_STATS; + if (prepare_schema_table(YYTHD, lex, 0, SCH_CLIENT_STATS)) + MYSQL_YYABORT; + } + | USER_STATS_SYM + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_SHOW_USER_STATS; + if (prepare_schema_table(YYTHD, lex, 0, SCH_USER_STATS)) + MYSQL_YYABORT; + } + | TABLE_STATS_SYM + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_SHOW_TABLE_STATS; + if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_STATS)) + MYSQL_YYABORT; + } + | INDEX_STATS_SYM + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_SHOW_INDEX_STATS; + if (prepare_schema_table(YYTHD, lex, 0, SCH_INDEX_STATS)) + MYSQL_YYABORT; + } | CREATE PROCEDURE sp_name { LEX *lex= Lex; @@ -10339,6 +10372,16 @@ flush_option: { Lex->type|= REFRESH_STATUS; } | SLAVE { Lex->type|= REFRESH_SLAVE; } + | SLOW_SYM QUERY_SYM LOGS_SYM + { Lex->type |= REFRESH_SLOW_QUERY_LOG; } + | CLIENT_STATS_SYM + { Lex->type|= REFRESH_CLIENT_STATS; } + | USER_STATS_SYM + { Lex->type|= REFRESH_USER_STATS; } + | TABLE_STATS_SYM + { Lex->type|= REFRESH_TABLE_STATS; } + | INDEX_STATS_SYM + { Lex->type|= REFRESH_INDEX_STATS; } | MASTER_SYM { Lex->type|= REFRESH_MASTER; } | DES_KEY_FILE @@ -11447,6 +11490,7 @@ keyword_sp: | CHAIN_SYM {} | CHANGED {} | CIPHER_SYM {} + | CLIENT_STATS_SYM {} | CLIENT_SYM {} | COALESCE {} | CODE_SYM {} @@ -11508,6 +11552,7 @@ keyword_sp: | HOSTS_SYM {} | HOUR_SYM {} | IDENTIFIED_SYM {} + | INDEX_STATS_SYM {} | INVOKER_SYM {} | IMPORT {} | INDEXES {} @@ -11631,6 +11676,7 @@ keyword_sp: | SIMPLE_SYM {} | SHARE_SYM {} | SHUTDOWN {} + | SLOW_SYM {} | SNAPSHOT_SYM {} | SOUNDS_SYM {} | SOURCE_SYM {} @@ -11650,6 +11696,7 @@ keyword_sp: | SUSPEND_SYM {} | SWAPS_SYM {} | SWITCHES_SYM {} + | TABLE_STATS_SYM {} | TABLES {} | TABLE_CHECKSUM_SYM {} | TABLESPACE {} @@ -11675,6 +11722,7 @@ keyword_sp: | UNKNOWN_SYM {} | UNTIL_SYM {} | USER {} + | USER_STATS_SYM {} | USE_FRM {} | VARIABLES {} | VIEW_SYM {} === modified file 'sql/structs.h' --- a/sql/structs.h 2009-06-26 19:57:42 +0000 +++ b/sql/structs.h 2009-10-19 17:14:48 +0000 @@ -76,6 +76,7 @@ typedef struct st_key { uint extra_length; uint usable_key_parts; /* Should normally be = key_parts */ uint block_size; + uint name_length; enum ha_key_alg algorithm; /* Note that parser is used when the table is opened for use, and @@ -88,6 +89,8 @@ typedef struct st_key { }; KEY_PART_INFO *key_part; char *name; /* Name of key */ + /* Unique name for cache; db + \0 + table_name + \0 + key_name + \0 */ + uchar *cache_name; /* Array of AVG(#records with the same field value) for 1st ... Nth key part. 0 means 'not known'. @@ -231,6 +234,111 @@ typedef struct user_conn { USER_RESOURCES user_resources; } USER_CONN; +typedef struct st_user_stats +{ + char user[max(USERNAME_LENGTH, LIST_PROCESS_HOST_LEN) + 1]; + // Account name the user is mapped to when this is a user from mapped_user. + // Otherwise, the same value as user. + char priv_user[max(USERNAME_LENGTH, LIST_PROCESS_HOST_LEN) + 1]; + uint user_name_length; + uint total_connections; + uint concurrent_connections; + time_t connected_time; // in seconds + double busy_time; // in seconds + double cpu_time; // in seconds + ulonglong bytes_received; + ulonglong bytes_sent; + ulonglong binlog_bytes_written; + ha_rows rows_read, rows_sent; + ha_rows rows_updated, rows_deleted, rows_inserted; + ulonglong select_commands, update_commands, other_commands; + ulonglong commit_trans, rollback_trans; + ulonglong denied_connections, lost_connections; + ulonglong access_denied_errors; + ulonglong empty_queries; +} USER_STATS; + +/* Lookup function for hash tables with USER_STATS entries */ +extern "C" uchar *get_key_user_stats(USER_STATS *user_stats, size_t *length, + my_bool not_used __attribute__((unused))); + +/* Free all memory for a hash table with USER_STATS entries */ +extern void free_user_stats(USER_STATS* user_stats); + +/* Intialize an instance of USER_STATS */ +extern void +init_user_stats(USER_STATS *user_stats, + const char *user, + size_t user_length, + const char *priv_user, + uint total_connections, + uint concurrent_connections, + time_t connected_time, + double busy_time, + double cpu_time, + ulonglong bytes_received, + ulonglong bytes_sent, + ulonglong binlog_bytes_written, + ha_rows rows_sent, + ha_rows rows_read, + ha_rows rows_inserted, + ha_rows rows_deleted, + ha_rows rows_updated, + ulonglong select_commands, + ulonglong update_commands, + ulonglong other_commands, + ulonglong commit_trans, + ulonglong rollback_trans, + ulonglong denied_connections, + ulonglong lost_connections, + ulonglong access_denied_errors, + ulonglong empty_queries); + +/* Increment values of an instance of USER_STATS */ +extern void +add_user_stats(USER_STATS *user_stats, + uint total_connections, + uint concurrent_connections, + time_t connected_time, + double busy_time, + double cpu_time, + ulonglong bytes_received, + ulonglong bytes_sent, + ulonglong binlog_bytes_written, + ha_rows rows_sent, + ha_rows rows_read, + ha_rows rows_inserted, + ha_rows rows_deleted, + ha_rows rows_updated, + ulonglong select_commands, + ulonglong update_commands, + ulonglong other_commands, + ulonglong commit_trans, + ulonglong rollback_trans, + ulonglong denied_connections, + ulonglong lost_connections, + ulonglong access_denied_errors, + ulonglong empty_queries); + +typedef struct st_table_stats +{ + char table[NAME_LEN * 2 + 2]; // [db] + '\0' + [table] + '\0' + uint table_name_length; + ulonglong rows_read, rows_changed; + ulonglong rows_changed_x_indexes; + /* Stores enum db_type, but forward declarations cannot be done */ + int engine_type; +} TABLE_STATS; + +typedef struct st_index_stats +{ + // [db] + '\0' + [table] + '\0' + [index] + '\0' + char index[NAME_LEN * 3 + 3]; + uint index_name_length; /* Length of 'index' */ + ulonglong rows_read; +} INDEX_STATS; + + /* Bits in form->update */ #define REG_MAKE_DUPP 1 /* Make a copy of record when read */ #define REG_NEW_RECORD 2 /* Write a new record if not found */ === modified file 'sql/table.cc' --- a/sql/table.cc 2009-09-09 21:06:57 +0000 +++ b/sql/table.cc 2009-10-19 17:14:48 +0000 @@ -1325,6 +1325,19 @@ static int open_binary_frm(THD *thd, TAB { uint usable_parts= 0; keyinfo->name=(char*) share->keynames.type_names[key]; + keyinfo->name_length= strlen(keyinfo->name); + keyinfo->cache_name= + (uchar*) alloc_root(&share->mem_root, + share->table_cache_key.length+ + keyinfo->name_length + 1); + if (keyinfo->cache_name) // If not out of memory + { + uchar *pos= keyinfo->cache_name; + memcpy(pos, share->table_cache_key.str, share->table_cache_key.length); + memcpy(pos + share->table_cache_key.length, keyinfo->name, + keyinfo->name_length+1); + } + /* Fix fulltext keys for old .frm files */ if (share->key_info[key].flags & HA_FULLTEXT) share->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT; === modified file 'sql/table.h' --- a/sql/table.h 2009-09-15 10:46:35 +0000 +++ b/sql/table.h 2009-10-19 17:14:48 +0000 @@ -878,6 +878,7 @@ typedef struct st_foreign_key_info enum enum_schema_tables { SCH_CHARSETS= 0, + SCH_CLIENT_STATS, SCH_COLLATIONS, SCH_COLLATION_CHARACTER_SET_APPLICABILITY, SCH_COLUMNS, @@ -887,6 +888,7 @@ enum enum_schema_tables SCH_FILES, SCH_GLOBAL_STATUS, SCH_GLOBAL_VARIABLES, + SCH_INDEX_STATS, SCH_KEY_COLUMN_USAGE, SCH_OPEN_TABLES, SCH_PARTITIONS, @@ -905,8 +907,10 @@ enum enum_schema_tables SCH_TABLE_CONSTRAINTS, SCH_TABLE_NAMES, SCH_TABLE_PRIVILEGES, + SCH_TABLE_STATS, SCH_TRIGGERS, SCH_USER_PRIVILEGES, + SCH_USER_STATS, SCH_VARIABLES, SCH_VIEWS }; === modified file 'sql/tztime.cc' --- a/sql/tztime.cc 2009-09-07 20:50:10 +0000 +++ b/sql/tztime.cc 2009-10-19 17:14:48 +0000 @@ -1676,7 +1676,7 @@ my_tz_init(THD *org_thd, const char *def tz_leapcnt= 0; - res= table->file->index_first(table->record[0]); + res= table->file->ha_index_first(table->record[0]); while (!res) { @@ -1698,7 +1698,7 @@ my_tz_init(THD *org_thd, const char *def tz_leapcnt, (ulong) tz_lsis[tz_leapcnt-1].ls_trans, tz_lsis[tz_leapcnt-1].ls_corr)); - res= table->file->index_next(table->record[0]); + res= table->file->ha_index_next(table->record[0]); } (void)table->file->ha_index_end(); @@ -1865,8 +1865,8 @@ tz_load_from_open_tables(const String *t */ (void)table->file->ha_index_init(0, 1); - if (table->file->index_read_map(table->record[0], table->field[0]->ptr, - HA_WHOLE_KEY, HA_READ_KEY_EXACT)) + if (table->file->ha_index_read_map(table->record[0], table->field[0]->ptr, + HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { #ifdef EXTRA_DEBUG /* @@ -1893,8 +1893,8 @@ tz_load_from_open_tables(const String *t table->field[0]->store((longlong) tzid, TRUE); (void)table->file->ha_index_init(0, 1); - if (table->file->index_read_map(table->record[0], table->field[0]->ptr, - HA_WHOLE_KEY, HA_READ_KEY_EXACT)) + if (table->file->ha_index_read_map(table->record[0], table->field[0]->ptr, + HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { sql_print_error("Can't find description of time zone '%u'", tzid); goto end; @@ -1920,8 +1920,8 @@ tz_load_from_open_tables(const String *t table->field[0]->store((longlong) tzid, TRUE); (void)table->file->ha_index_init(0, 1); - res= table->file->index_read_map(table->record[0], table->field[0]->ptr, - (key_part_map)1, HA_READ_KEY_EXACT); + res= table->file->ha_index_read_map(table->record[0], table->field[0]->ptr, + (key_part_map)1, HA_READ_KEY_EXACT); while (!res) { ttid= (uint)table->field[1]->val_int(); @@ -1968,8 +1968,8 @@ tz_load_from_open_tables(const String *t tmp_tz_info.typecnt= ttid + 1; - res= table->file->index_next_same(table->record[0], - table->field[0]->ptr, 4); + res= table->file->ha_index_next_same(table->record[0], + table->field[0]->ptr, 4); } if (res != HA_ERR_END_OF_FILE) @@ -1991,8 +1991,8 @@ tz_load_from_open_tables(const String *t table->field[0]->store((longlong) tzid, TRUE); (void)table->file->ha_index_init(0, 1); - res= table->file->index_read_map(table->record[0], table->field[0]->ptr, - (key_part_map)1, HA_READ_KEY_EXACT); + res= table->file->ha_index_read_map(table->record[0], table->field[0]->ptr, + (key_part_map)1, HA_READ_KEY_EXACT); while (!res) { ttime= (my_time_t)table->field[1]->val_int(); @@ -2021,8 +2021,8 @@ tz_load_from_open_tables(const String *t ("time_zone_transition table: tz_id: %u tt_time: %lu tt_id: %u", tzid, (ulong) ttime, ttid)); - res= table->file->index_next_same(table->record[0], - table->field[0]->ptr, 4); + res= table->file->ha_index_next_same(table->record[0], + table->field[0]->ptr, 4); } /*
participants (1)
-
Michael Widenius