]> git.pld-linux.org Git - packages/mysql.git/commitdiff
- percona patches
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Sat, 6 Dec 2008 20:46:10 +0000 (20:46 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    mysql-acc-pslist.patch -> 1.2
    mysql-microslow.patch -> 1.1

mysql-acc-pslist.patch [new file with mode: 0644]
mysql-microslow.patch [new file with mode: 0644]

diff --git a/mysql-acc-pslist.patch b/mysql-acc-pslist.patch
new file mode 100644 (file)
index 0000000..f54950e
--- /dev/null
@@ -0,0 +1,115 @@
+diff -r 174803e7e869 mysql-test/r/create.result
+--- a/mysql-test/r/create.result       Thu Sep 04 12:17:56 2008 -0700
++++ b/mysql-test/r/create.result       Thu Sep 04 12:20:19 2008 -0700
+@@ -1720,7 +1720,8 @@
+   `COMMAND` varchar(16) NOT NULL DEFAULT '',
+   `TIME` bigint(7) NOT NULL DEFAULT '0',
+   `STATE` varchar(64) DEFAULT NULL,
+-  `INFO` longtext
++  `INFO` longtext,
++  `TIME_MS` decimal(22,3) NOT NULL DEFAULT '0.000'
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8
+ drop table t1;
+ create temporary table t1 like information_schema.processlist;
+@@ -1734,7 +1735,8 @@
+   `COMMAND` varchar(16) NOT NULL DEFAULT '',
+   `TIME` bigint(7) NOT NULL DEFAULT '0',
+   `STATE` varchar(64) DEFAULT NULL,
+-  `INFO` longtext
++  `INFO` longtext,
++  `TIME_MS` decimal(22,3) NOT NULL DEFAULT '0.000'
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8
+ drop table t1;
+ create table t1 like information_schema.character_sets;
+diff -r 174803e7e869 mysql-test/r/not_embedded_server.result
+--- a/mysql-test/r/not_embedded_server.result  Thu Sep 04 12:17:56 2008 -0700
++++ b/mysql-test/r/not_embedded_server.result  Thu Sep 04 12:20:19 2008 -0700
+@@ -1,7 +1,7 @@
+ prepare stmt1 from ' SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND!=\'Daemon\' ';
+ execute stmt1;
+-ID    USER    HOST    DB      COMMAND TIME    STATE   INFO
+-number        root    localhost       test    Query   time    executing       SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND!='Daemon'
++ID    USER    HOST    DB      COMMAND TIME    STATE   INFO    TIME_MS
++number        root    localhost       test    Query   time    executing       SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND!='Daemon'    time_ms
+ deallocate prepare stmt1;
+ FLUSH STATUS;
+ SHOW GLOBAL STATUS LIKE 'com_select';
+diff -r 174803e7e869 mysql-test/t/not_embedded_server.test
+--- a/mysql-test/t/not_embedded_server.test    Thu Sep 04 12:17:56 2008 -0700
++++ b/mysql-test/t/not_embedded_server.test    Thu Sep 04 12:20:19 2008 -0700
+@@ -16,7 +16,7 @@
+ # End of 4.1 tests
+ prepare stmt1 from ' SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND!=\'Daemon\' ';
+---replace_column 1 number 6 time 3 localhost
++--replace_column 1 number 6 time 3 localhost 9 time_ms
+ execute stmt1;
+ deallocate prepare stmt1;
+diff -r 174803e7e869 patch_info/acc-pslist.info
+--- /dev/null  Thu Jan 01 00:00:00 1970 +0000
++++ b/patch_info/acc-pslist.info       Thu Sep 04 12:20:19 2008 -0700
+@@ -0,0 +1,6 @@
++File=acc-pslist.patch
++Name=Milliseconds in PROCESSLIST
++Version=1.0
++Author=Percona <info@percona.com>
++License=GPL
++Comment=
+diff -r 174803e7e869 sql/sql_show.cc
+--- a/sql/sql_show.cc  Thu Sep 04 12:17:56 2008 -0700
++++ b/sql/sql_show.cc  Thu Sep 04 12:20:19 2008 -0700
+@@ -1803,7 +1803,7 @@
+   TABLE *table= tables->table;
+   CHARSET_INFO *cs= system_charset_info;
+   char *user;
+-  time_t now= my_time(0);
++  ulonglong unow= my_micro_time();
+   DBUG_ENTER("fill_process_list");
+   user= thd->security_ctx->master_access & PROCESS_ACL ?
+@@ -1861,8 +1861,8 @@
+         table->field[4]->store(command_name[tmp->command].str,
+                                command_name[tmp->command].length, cs);
+       /* MYSQL_TIME */
+-      table->field[5]->store((uint32)(tmp->start_time ?
+-                                      now - tmp->start_time : 0), TRUE);
++      const ulonglong utime= tmp->start_utime ? unow - tmp->start_utime : 0;
++      table->field[5]->store(utime / 1000000, TRUE);
+       /* STATE */
+ #ifndef EMBEDDED_LIBRARY
+       val= (char*) (tmp->locked ? "Locked" :
+@@ -1896,11 +1896,15 @@
+         table->field[7]->set_notnull();
+       }
++      /* TIME_MS */
++      table->field[8]->store((double)(utime / 1000.0));
++
+       if (schema_table_store_record(thd, table))
+       {
+         VOID(pthread_mutex_unlock(&LOCK_thread_count));
+         DBUG_RETURN(1);
+       }
++
+     }
+   }
+@@ -5532,7 +5536,7 @@
+     into it two numbers, based on modulus of base-10 numbers.  In the ones
+     position is the number of decimals.  Tens position is unused.  In the
+     hundreds and thousands position is a two-digit decimal number representing
+-    length.  Encode this value with  (decimals*100)+length  , where
++    length.  Encode this value with  (length*100)+decimals  , where
+     0<decimals<10 and 0<=length<100 .
+   @param
+@@ -6540,6 +6544,8 @@
+   {"STATE", 64, MYSQL_TYPE_STRING, 0, 1, "State", SKIP_OPEN_TABLE},
+   {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info",
+    SKIP_OPEN_TABLE},
++  {"TIME_MS", 100 * (MY_INT64_NUM_DECIMAL_DIGITS + 1) + 3, MYSQL_TYPE_DECIMAL,
++    0, 0, "Time_ms", SKIP_OPEN_TABLE},
+   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
+ };
diff --git a/mysql-microslow.patch b/mysql-microslow.patch
new file mode 100644 (file)
index 0000000..e2321f5
--- /dev/null
@@ -0,0 +1,710 @@
+diff -r debbd352c16a patch_info/microslow.info
+--- /dev/null  Thu Jan 01 00:00:00 1970 +0000
++++ b/patch_info/microslow.info        Thu Sep 04 12:16:10 2008 -0700
+@@ -0,0 +1,6 @@
++File=microslow.patch
++Name=Extended statistics in slow.log
++Version=1.0
++Author=Percona <info@percona.com>
++License=GPL
++Comment=
+diff -r debbd352c16a sql/event_scheduler.cc
+--- a/sql/event_scheduler.cc   Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/event_scheduler.cc   Thu Sep 04 12:16:10 2008 -0700
+@@ -192,6 +192,7 @@
+   thd->client_capabilities|= CLIENT_MULTI_RESULTS;
+   pthread_mutex_lock(&LOCK_thread_count);
+   thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
++  thd->write_to_slow_log = TRUE;
+   pthread_mutex_unlock(&LOCK_thread_count);
+   /*
+diff -r debbd352c16a sql/filesort.cc
+--- a/sql/filesort.cc  Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/filesort.cc  Thu Sep 04 12:16:10 2008 -0700
+@@ -188,6 +188,7 @@
+   {
+     status_var_increment(thd->status_var.filesort_scan_count);
+   }
++  thd->query_plan_flags|= QPLAN_FILESORT;
+ #ifdef CAN_TRUST_RANGE
+   if (select && select->quick && select->quick->records > 0L)
+   {
+@@ -253,6 +254,7 @@
+   }
+   else
+   {
++    thd->query_plan_flags|= QPLAN_FILESORT_DISK;
+     if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
+     {
+       x_free(table_sort.buffpek);
+@@ -1162,6 +1164,7 @@
+   DBUG_ENTER("merge_buffers");
+   status_var_increment(current_thd->status_var.filesort_merge_passes);
++  current_thd->query_plan_fsort_passes++;
+   if (param->not_killable)
+   {
+     killed= &not_killable;
+diff -r debbd352c16a sql/log.cc
+--- a/sql/log.cc       Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/log.cc       Thu Sep 04 12:16:10 2008 -0700
+@@ -955,7 +955,7 @@
+     /* fill in user_host value: the format is "%s[%s] @ %s [%s]" */
+     user_host_len= (strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
+                              sctx->priv_user ? sctx->priv_user : "", "[",
+-                             sctx->user ? sctx->user : "", "] @ ",
++                             sctx->user ? sctx->user : (thd->slave_thread ? "SQL_SLAVE" : ""), "] @ ",
+                              sctx->host ? sctx->host : "", " [",
+                              sctx->ip ? sctx->ip : "", "]", NullS) -
+                     user_host_buff);
+@@ -977,6 +977,13 @@
+       query= command_name[thd->command].str;
+       query_length= command_name[thd->command].length;
+     }
++
++    if (!query_length) 
++    { 
++      thd->sent_row_count= thd->examined_row_count= 0; 
++      thd->query_plan_flags= QPLAN_NONE; 
++      thd->query_plan_fsort_passes= 0; 
++    } 
+     for (current_handler= slow_log_handler_list; *current_handler ;)
+       error= (*current_handler++)->log_slow(thd, current_time, thd->start_time,
+@@ -2233,16 +2240,31 @@
+       if (my_b_write(&log_file, (uchar*) "\n", 1))
+         tmp_errno= errno;
+     }
++    
+     /* For slow query log */
+     sprintf(query_time_buff, "%.6f", ulonglong2double(query_utime)/1000000.0);
+     sprintf(lock_time_buff,  "%.6f", ulonglong2double(lock_utime)/1000000.0);
+     if (my_b_printf(&log_file,
+-                    "# Query_time: %s  Lock_time: %s"
+-                    " Rows_sent: %lu  Rows_examined: %lu\n",
++                    "# Thread_id: %lu  Schema: %s\n" \
++                    "# Query_time: %s  Lock_time: %s  Rows_sent: %lu  Rows_examined: %lu\n",
++                    (ulong) thd->thread_id, (thd->db ? thd->db : ""),
+                     query_time_buff, lock_time_buff,
+                     (ulong) thd->sent_row_count,
+                     (ulong) thd->examined_row_count) == (uint) -1)
+       tmp_errno= errno;
++     if ((thd->variables.log_slow_verbosity & SLOG_V_QUERY_PLAN) && 
++         my_b_printf(&log_file, 
++                     "# QC_Hit: %s  Full_scan: %s  Full_join: %s  Tmp_table: %s  Tmp_table_on_disk: %s\n" \
++                     "# Filesort: %s  Filesort_on_disk: %s  Merge_passes: %lu\n", 
++                     ((thd->query_plan_flags & QPLAN_QC) ? "Yes" : "No"), 
++                     ((thd->query_plan_flags & QPLAN_FULL_SCAN) ? "Yes" : "No"), 
++                     ((thd->query_plan_flags & QPLAN_FULL_JOIN) ? "Yes" : "No"), 
++                     ((thd->query_plan_flags & QPLAN_TMP_TABLE) ? "Yes" : "No"), 
++                     ((thd->query_plan_flags & QPLAN_TMP_DISK) ? "Yes" : "No"), 
++                     ((thd->query_plan_flags & QPLAN_FILESORT) ? "Yes" : "No"), 
++                     ((thd->query_plan_flags & QPLAN_FILESORT_DISK) ? "Yes" : "No"), 
++                     thd->query_plan_fsort_passes) == (uint) -1) 
++       tmp_errno=errno; 
+     if (thd->db && strcmp(thd->db, db))
+     {                                         // Database changed
+       if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1)
+diff -r debbd352c16a sql/mysql_priv.h
+--- a/sql/mysql_priv.h Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/mysql_priv.h Thu Sep 04 12:16:10 2008 -0700
+@@ -595,6 +595,73 @@
+ #define WEEK_FIRST_WEEKDAY   4
+ #define STRING_BUFFER_USUAL_SIZE 80
++
++/* Slow log */
++
++struct msl_opts
++{
++  ulong val;
++  const char *name;
++};
++
++#define SLOG_V_QUERY_PLAN     1 << 1
++/* ... */
++#define SLOG_V_INVALID        1 << 31
++#define SLOG_V_NONE           1 << 0
++
++static const struct msl_opts slog_verb[]= 
++{
++  /* Basic flags */
++
++  { SLOG_V_QUERY_PLAN, "query_plan" },
++
++  /* End of baisc flags */
++
++  { 0, "" },
++
++  /* Complex flags */
++
++  { SLOG_V_QUERY_PLAN, "standard" },
++  { SLOG_V_INVALID, "full" },
++
++  /* End of complex flags */
++
++  { SLOG_V_INVALID, (char *)0 }
++};
++
++#define QPLAN_NONE            0
++#define QPLAN_QC              1 << 0
++#define QPLAN_QC_NO           1 << 1
++#define QPLAN_FULL_SCAN       1 << 2
++#define QPLAN_FULL_JOIN       1 << 3
++#define QPLAN_TMP_TABLE       1 << 4
++#define QPLAN_TMP_DISK        1 << 5
++#define QPLAN_FILESORT        1 << 6
++#define QPLAN_FILESORT_DISK   1 << 7
++/* ... */
++#define QPLAN_MAX             1 << 31
++
++#define SLOG_F_QC_NO          QPLAN_QC_NO
++#define SLOG_F_FULL_SCAN      QPLAN_FULL_SCAN
++#define SLOG_F_FULL_JOIN      QPLAN_FULL_JOIN
++#define SLOG_F_TMP_TABLE      QPLAN_TMP_TABLE
++#define SLOG_F_TMP_DISK       QPLAN_TMP_DISK
++#define SLOG_F_FILESORT       QPLAN_FILESORT
++#define SLOG_F_FILESORT_DISK  QPLAN_FILESORT_DISK
++#define SLOG_F_INVALID        1 << 31
++#define SLOG_F_NONE           0
++
++static const struct msl_opts slog_filter[]= 
++{
++  { SLOG_F_QC_NO,         "qc_miss" },
++  { SLOG_F_FULL_SCAN,     "full_scan" },
++  { SLOG_F_FULL_JOIN,     "full_join" },
++  { SLOG_F_TMP_TABLE,     "tmp_table" },
++  { SLOG_F_TMP_DISK,      "tmp_table_on_disk" },
++  { SLOG_F_FILESORT,      "filesort" },
++  { SLOG_F_FILESORT_DISK, "filesort_on_disk" },
++  { SLOG_F_INVALID,       (char *)0 }
++};
+ /*
+   Some defines for exit codes for ::is_equal class functions.
+diff -r debbd352c16a sql/mysqld.cc
+--- a/sql/mysqld.cc    Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/mysqld.cc    Thu Sep 04 12:16:10 2008 -0700
+@@ -5553,6 +5553,9 @@
+   OPT_SECURE_FILE_PRIV,
+   OPT_MIN_EXAMINED_ROW_LIMIT,
+   OPT_LOG_SLOW_SLAVE_STATEMENTS,
++  OPT_LOG_SLOW_RATE_LIMIT, 
++  OPT_LOG_SLOW_VERBOSITY, 
++  OPT_LOG_SLOW_FILTER, 
+   OPT_OLD_MODE,
+   OPT_SLAVE_EXEC_MODE
+ };
+@@ -6467,6 +6470,17 @@
+    (uchar**) 0,
+    0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
+    1, 100, 0, 1, 0},
++  {"log_slow_filter", OPT_LOG_SLOW_FILTER,
++   "Log only the queries that followed certain execution plan. Multiple flags allowed in a comma-separated string. [qc_miss, full_scan, full_join, tmp_table, tmp_table_on_disk, filesort, filesort_on_disk]",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, SLOG_F_NONE, 0, 0},
++  {"log_slow_rate_limit", OPT_LOG_SLOW_RATE_LIMIT,
++   "Rate limit statement writes to slow log to only those from every (1/log_slow_rate_limit) session.",
++   (uchar**) &global_system_variables.log_slow_rate_limit,
++   (uchar**) &max_system_variables.log_slow_rate_limit, 0, GET_ULONG,
++   REQUIRED_ARG, 1, 1, ~0L, 0, 1L, 0},
++  {"log_slow_verbosity", OPT_LOG_SLOW_VERBOSITY,
++   "Choose how verbose the messages to your slow log will be. Multiple flags allowed in a comma-separated string. [microtime, query_plan, innodb]",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, SLOG_V_NONE, 0, 0},
+   {"long_query_time", OPT_LONG_QUERY_TIME,
+    "Log all queries that have taken more than long_query_time seconds to execute to file. "
+    "The argument will be treated as a decimal value with microsecond precission.",
+@@ -7542,6 +7556,10 @@
+   global_system_variables.old_passwords= 0;
+   global_system_variables.old_alter_table= 0;
+   global_system_variables.binlog_format= BINLOG_FORMAT_UNSPEC;
++  
++  global_system_variables.log_slow_verbosity= SLOG_V_NONE; 
++  global_system_variables.log_slow_filter= SLOG_F_NONE; 
++  
+   /*
+     Default behavior for 4.1 and 5.0 is to treat NULL values as unequal
+     when collecting index statistics for MyISAM tables.
+@@ -7988,6 +8006,24 @@
+   case OPT_BOOTSTRAP:
+     opt_noacl=opt_bootstrap=1;
+     break;
++  case OPT_LOG_SLOW_FILTER: 
++    if ((global_system_variables.log_slow_filter=  
++          msl_flag_resolve_by_name(slog_filter, argument, 
++                                   SLOG_F_NONE, SLOG_F_INVALID)) == SLOG_F_INVALID) 
++    { 
++      fprintf(stderr,"Invalid argument to log_slow_filter\n"); 
++      exit(1); 
++    } 
++    break; 
++  case OPT_LOG_SLOW_VERBOSITY: 
++    if ((global_system_variables.log_slow_verbosity=  
++         msl_flag_resolve_by_name(slog_verb, argument, 
++                                  SLOG_V_NONE, SLOG_V_INVALID)) == SLOG_V_INVALID) 
++    { 
++      fprintf(stderr,"Invalid argument to log_slow_verbosity\n"); 
++      exit(1); 
++    } 
++    break; 
+   case OPT_SERVER_ID:
+     server_id_supplied = 1;
+     break;
+diff -r debbd352c16a sql/set_var.cc
+--- a/sql/set_var.cc   Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/set_var.cc   Thu Sep 04 12:16:10 2008 -0700
+@@ -336,6 +336,20 @@
+                                             &SV::max_join_size,
+                                             fix_max_join_size);
+ #endif
++static sys_var_thd_ulong  sys_log_slow_rate_limit(&vars, "log_slow_rate_limit", 
++              &SV::log_slow_rate_limit); 
++static sys_var_thd_msl_flag sys_log_slow_filter(&vars, "log_slow_filter", 
++              &SV::log_slow_filter, 
++                                       SLOG_F_NONE, 
++                                       SLOG_F_NONE, 
++                                       SLOG_F_INVALID, 
++                                       slog_filter); 
++static sys_var_thd_msl_flag sys_log_slow_verbosity(&vars, "log_slow_verbosity", 
++              &SV::log_slow_verbosity, 
++                                       SLOG_V_NONE, 
++                                       SLOG_V_NONE, 
++                                       SLOG_V_INVALID, 
++                                       slog_verb); 
+ static sys_var_long_ptr_global
+ sys_max_prepared_stmt_count(&vars, "max_prepared_stmt_count",
+                             &max_prepared_stmt_count,
+@@ -3605,6 +3619,192 @@
+ #endif
+ }
++/* Slow log stuff */
++
++ulong msl_option_resolve_by_name(const struct msl_opts *opts, const char *name, ulong len)
++{
++  ulong i;
++  
++  for (i=0; opts[i].name; i++)
++  {
++    if (!my_strnncoll(&my_charset_latin1,
++                      (const uchar *)name, len,
++                      (const uchar *)opts[i].name, strlen(opts[i].name)))
++      return opts[i].val;
++  }
++  return opts[i].val;
++}
++
++ulong msl_flag_resolve_by_name(const struct msl_opts *opts, const char *names_list, 
++                               const ulong none_val, const ulong invalid_val)
++{
++  const char *p, *e;
++  ulong val= none_val;
++  
++  if (!*names_list)
++    return val;
++  
++  for (p= e= names_list; ; e++)
++  {
++    ulong i;
++    
++    if (*e != ',' && *e)
++      continue;
++    for (i=0; opts[i].name; i++)
++    {
++      if (!my_strnncoll(&my_charset_latin1,
++                        (const uchar *)p, e - p,
++                        (const uchar *)opts[i].name, strlen(opts[i].name)))
++      {
++        val= val | opts[i].val;
++        break;
++      }
++    }
++    if (opts[i].val == invalid_val)
++      return invalid_val;
++    if (!*e)
++      break;
++    p= e + 1;
++  }
++  return val;
++}
++
++const char *msl_option_get_name(const struct msl_opts *opts, ulong val)
++{
++  for (ulong i=0; opts[i].name && opts[i].name[0]; i++)
++  {
++    if (opts[i].val == val)
++      return opts[i].name;
++  }
++  return "*INVALID*";
++}
++
++char *msl_flag_get_name(const struct msl_opts *opts, char *buf, ulong val)
++{
++  uint offset= 0;
++  
++  *buf= '\0';
++  for (ulong i=0; opts[i].name && opts[i].name[0]; i++)
++  {
++    if (opts[i].val & val)
++      offset+= snprintf(buf+offset, STRING_BUFFER_USUAL_SIZE - offset - 1,
++                        "%s%s", (offset ? "," : ""), opts[i].name);
++  }
++  return buf;
++}
++
++/****************************************************************************
++ Functions to handle log_slow_verbosity
++****************************************************************************/
++
++/* Based upon sys_var::check_enum() */
++
++bool sys_var_thd_msl_option::check(THD *thd, set_var *var)
++{
++  char buff[STRING_BUFFER_USUAL_SIZE];
++  String str(buff, sizeof(buff), &my_charset_latin1), *res;
++
++  if (var->value->result_type() == STRING_RESULT)
++  {
++    ulong verb= this->invalid_val;
++    if (!(res=var->value->val_str(&str)) ||
++            (var->save_result.ulong_value=
++          (ulong) (verb= msl_option_resolve_by_name(this->opts, res->ptr(), res->length()))) == this->invalid_val)
++      goto err;
++    return 0;
++  }
++
++err:
++  my_error(ER_WRONG_ARGUMENTS, MYF(0), var->var->name);
++  return 1;
++}
++
++uchar *sys_var_thd_msl_option::value_ptr(THD *thd, enum_var_type type,
++                                      LEX_STRING *base)
++{
++  ulong val;
++  val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
++        thd->variables.*offset);
++  const char *verbosity= msl_option_get_name(this->opts, val);
++  return (uchar *) verbosity;
++}
++
++
++void sys_var_thd_msl_option::set_default(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    global_system_variables.*offset= (ulong) this->default_val;
++  else
++    thd->variables.*offset= (ulong) (global_system_variables.*offset);
++}
++
++
++bool sys_var_thd_msl_option::update(THD *thd, set_var *var)
++{
++  if (var->type == OPT_GLOBAL)
++    global_system_variables.*offset= var->save_result.ulong_value;
++  else
++    thd->variables.*offset= var->save_result.ulong_value;
++  return 0;
++}
++
++/****************************************************************************
++ Functions to handle log_slow_filter
++****************************************************************************/
++  
++/* Based upon sys_var::check_enum() */
++
++bool sys_var_thd_msl_flag::check(THD *thd, set_var *var)
++{
++  char buff[2 * STRING_BUFFER_USUAL_SIZE];
++  String str(buff, sizeof(buff), &my_charset_latin1), *res;
++
++  if (var->value->result_type() == STRING_RESULT)
++  {
++    ulong filter= this->none_val;
++    if (!(res=var->value->val_str(&str)) ||
++       (var->save_result.ulong_value=
++          (ulong) (filter= msl_flag_resolve_by_name(this->flags, res->ptr(), this->none_val, 
++                                                    this->invalid_val))) == this->invalid_val)
++      goto err;
++    return 0;
++  }
++
++err:
++  my_error(ER_WRONG_ARGUMENTS, MYF(0), var->var->name);
++  return 1;
++}
++
++uchar *sys_var_thd_msl_flag::value_ptr(THD *thd, enum_var_type type,
++                                      LEX_STRING *base)
++{
++  ulong val;
++  val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
++        thd->variables.*offset);
++  msl_flag_get_name(this->flags, this->flags_string, val);
++  return (uchar *) this->flags_string;
++}
++
++
++void sys_var_thd_msl_flag::set_default(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    global_system_variables.*offset= (ulong) this->default_val;
++  else
++    thd->variables.*offset= (ulong) (global_system_variables.*offset);
++}
++
++
++bool sys_var_thd_msl_flag::update(THD *thd, set_var *var)
++{
++  if (var->type == OPT_GLOBAL)
++    global_system_variables.*offset= var->save_result.ulong_value;
++  else
++    thd->variables.*offset= var->save_result.ulong_value;
++  return 0;
++}
++
++
+ /****************************************************************************
+  Functions to handle table_type
+ ****************************************************************************/
+diff -r debbd352c16a sql/set_var.h
+--- a/sql/set_var.h    Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/set_var.h    Thu Sep 04 12:16:10 2008 -0700
+@@ -1057,6 +1057,68 @@
+   bool update(THD *thd, set_var *var);
+ };
++class sys_var_thd_msl_option :public sys_var_thd
++{
++protected:
++  ulong SV::*offset;
++  const ulong none_val;
++  const ulong default_val;
++  const ulong invalid_val;
++  const struct msl_opts *opts;
++public:
++  sys_var_thd_msl_option(sys_var_chain *chain, const char *name_arg,
++                         ulong SV::*offset_arg,
++                         const ulong none_val_arg,
++                         const ulong default_val_arg,
++                         const ulong invalid_val_arg,
++                         const struct msl_opts *opts_arg)
++    :sys_var_thd(name_arg), offset(offset_arg), none_val(none_val_arg),
++     default_val(default_val_arg), invalid_val(invalid_val_arg), 
++     opts(opts_arg)
++  { chain_sys_var(chain); }
++  bool check(THD *thd, set_var *var);
++  SHOW_TYPE show_type() { return SHOW_CHAR; }
++  bool check_update_type(Item_result type)
++  {
++    return type != STRING_RESULT;             /* Only accept strings */
++  }
++  void set_default(THD *thd, enum_var_type type);
++  bool update(THD *thd, set_var *var);
++  uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
++};
++
++
++class sys_var_thd_msl_flag :public sys_var_thd
++{
++protected:
++  char flags_string[2 * STRING_BUFFER_USUAL_SIZE];
++  ulong SV::*offset;
++  const ulong none_val;
++  const ulong default_val;
++  const ulong invalid_val;
++  const struct msl_opts *flags;
++public:
++  sys_var_thd_msl_flag(sys_var_chain *chain, const char *name_arg,
++                       ulong SV::*offset_arg, 
++                       const ulong none_val_arg, 
++                       const ulong default_val_arg, 
++                       const ulong invalid_val_arg,
++                       const struct msl_opts *flags_arg)
++    :sys_var_thd(name_arg), offset(offset_arg), none_val(none_val_arg),
++     default_val(default_val_arg), invalid_val(invalid_val_arg), 
++     flags(flags_arg)
++  { chain_sys_var(chain); }
++  bool check(THD *thd, set_var *var);
++  SHOW_TYPE show_type() { return SHOW_CHAR; }
++  bool check_update_type(Item_result type)
++  {
++    return type != STRING_RESULT;             /* Only accept strings */
++  }
++  void set_default(THD *thd, enum_var_type type);
++  bool update(THD *thd, set_var *var);
++  uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
++};
++
+ /**
+   Handler for setting the system variable --read-only.
+@@ -1322,3 +1384,10 @@
+ bool process_key_caches(process_key_cache_t func);
+ void delete_elements(I_List<NAMED_LIST> *list,
+                    void (*free_element)(const char*, uchar*));
++
++/* Slow log functions */
++ulong msl_option_resolve_by_name(const struct msl_opts *opts, const char *name, ulong len);
++ulong msl_flag_resolve_by_name(const struct msl_opts *opts, const char *names_list, 
++                               const ulong none_val, const ulong invalid_val);
++const char *msl_option_get_name(const struct msl_opts *opts, ulong val);
++char *msl_flag_get_name(const struct msl_opts *opts, char *buf, ulong val);
+diff -r debbd352c16a sql/slave.cc
+--- a/sql/slave.cc     Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/slave.cc     Thu Sep 04 12:16:10 2008 -0700
+@@ -1561,6 +1561,7 @@
+     + MAX_LOG_EVENT_HEADER;  /* note, incr over the global not session var */
+   thd->slave_thread = 1;
+   thd->enable_slow_log= opt_log_slow_slave_statements;
++  thd->write_to_slow_log= opt_log_slow_slave_statements;
+   set_slave_thread_options(thd);
+   thd->client_capabilities = CLIENT_LOCAL_FILES;
+   pthread_mutex_lock(&LOCK_thread_count);
+diff -r debbd352c16a sql/sql_cache.cc
+--- a/sql/sql_cache.cc Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/sql_cache.cc Thu Sep 04 12:16:10 2008 -0700
+@@ -1465,6 +1465,7 @@
+   thd->limit_found_rows = query->found_rows();
+   thd->status_var.last_query_cost= 0.0;
++  thd->query_plan_flags|= QPLAN_QC;
+   thd->main_da.disable_status();
+   BLOCK_UNLOCK_RD(query_block);
+@@ -1473,6 +1474,7 @@
+ err_unlock:
+   STRUCT_UNLOCK(&structure_guard_mutex);
+ err:
++  thd->query_plan_flags|= QPLAN_QC_NO;
+   DBUG_RETURN(0);                             // Query was not cached
+ }
+diff -r debbd352c16a sql/sql_class.h
+--- a/sql/sql_class.h  Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/sql_class.h  Thu Sep 04 12:16:10 2008 -0700
+@@ -396,6 +396,11 @@
+   DATE_TIME_FORMAT *datetime_format;
+   DATE_TIME_FORMAT *time_format;
+   my_bool sysdate_is_now;
++
++  ulong log_slow_rate_limit;
++  ulong log_slow_filter;
++  ulong log_slow_verbosity;
++
+ };
+@@ -1322,6 +1326,11 @@
+   
+   thr_lock_type update_lock_default;
+   Delayed_insert *di;
++
++  bool       write_to_slow_log; 
++ 
++  ulong      query_plan_flags; 
++  ulong      query_plan_fsort_passes; 
+   /* <> 0 if we are inside of trigger or stored function. */
+   uint in_sub_stmt;
+diff -r debbd352c16a sql/sql_connect.cc
+--- a/sql/sql_connect.cc       Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/sql_connect.cc       Thu Sep 04 12:16:10 2008 -0700
+@@ -1124,6 +1124,15 @@
+     prepare_new_connection_state(thd);
++    /* 
++      If rate limiting of slow log writes is enabled, decide whether to log this 
++      new thread's queries or not. Uses extremely simple algorithm. :) 
++    */ 
++    thd->write_to_slow_log= FALSE; 
++    if (thd->variables.log_slow_rate_limit <= 1 ||  
++        (thd->thread_id % thd->variables.log_slow_rate_limit) == 0) 
++         thd->write_to_slow_log= TRUE; 
++
+     while (!net->error && net->vio != 0 &&
+            !(thd->killed == THD::KILL_CONNECTION))
+     {
+diff -r debbd352c16a sql/sql_parse.cc
+--- a/sql/sql_parse.cc Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/sql_parse.cc Thu Sep 04 12:16:10 2008 -0700
+@@ -1629,6 +1629,27 @@
+   if (unlikely(thd->in_sub_stmt))
+     DBUG_VOID_RETURN;                           // Don't set time for sub stmt
++  /* Follow the slow log filter configuration. */ 
++  if (thd->variables.log_slow_filter != SLOG_F_NONE &&  
++      (!(thd->variables.log_slow_filter & thd->query_plan_flags) || 
++       ((thd->variables.log_slow_filter & SLOG_F_QC_NO) &&  
++        (thd->query_plan_flags & QPLAN_QC)))) 
++    DBUG_VOID_RETURN; 
++ 
++  /* 
++    Low long_query_time value most likely means user is debugging stuff and even  
++    though some thread's queries are not supposed to be logged b/c of the rate  
++    limit, if one of them takes long enough (>= 1 second) it will be sensible  
++    to make an exception and write to slow log anyway. 
++  */ 
++  if (thd->write_to_slow_log != TRUE && thd->variables.long_query_time < 1000000 && 
++      (ulong) (thd->start_utime - thd->utime_after_lock) >= 1000000) 
++    thd->write_to_slow_log= TRUE; 
++ 
++  /* Do not log this thread's queries due to rate limiting. */ 
++  if (thd->write_to_slow_log != TRUE) 
++    DBUG_VOID_RETURN; 
++
+   /*
+     Do not log administrative statements unless the appropriate option is
+     set; do not log into slow log if reading from backup.
+@@ -5640,6 +5661,9 @@
+   thd->total_warn_count=0;                    // Warnings for this query
+   thd->rand_used= 0;
+   thd->sent_row_count= thd->examined_row_count= 0;
++
++  thd->query_plan_flags= QPLAN_NONE; 
++  thd->query_plan_fsort_passes= 0; 
+   /*
+     Because we come here only for start of top-statements, binlog format is
+diff -r debbd352c16a sql/sql_select.cc
+--- a/sql/sql_select.cc        Thu Sep 04 12:13:31 2008 -0700
++++ b/sql/sql_select.cc        Thu Sep 04 12:16:10 2008 -0700
+@@ -6479,7 +6479,10 @@
+         {
+           join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
+           if (statistics)
++          {
+             status_var_increment(join->thd->status_var.select_scan_count);
++            join->thd->query_plan_flags|= QPLAN_FULL_SCAN;
++          }
+         }
+       }
+       else
+@@ -6493,7 +6496,10 @@
+         {
+           join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
+           if (statistics)
++          {
+             status_var_increment(join->thd->status_var.select_full_join_count);
++            join->thd->query_plan_flags|= QPLAN_FULL_JOIN;
++          }
+         }
+       }
+       if (!table->no_keyread)
+@@ -9629,6 +9635,7 @@
+               (ulong) rows_limit,test(group)));
+   status_var_increment(thd->status_var.created_tmp_tables);
++  thd->query_plan_flags|= QPLAN_TMP_TABLE;
+   if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES))
+     temp_pool_slot = bitmap_lock_set_next(&temp_pool);
+@@ -10499,6 +10506,7 @@
+     goto err;
+   }
+   status_var_increment(table->in_use->status_var.created_tmp_disk_tables);
++  table->in_use->query_plan_flags|= QPLAN_TMP_DISK;
+   share->db_record_offset= 1;
+   DBUG_RETURN(0);
+  err:
This page took 0.057882 seconds and 4 git commands to generate.