List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:December 21 2007 10:49am
Subject:bk commit into 5.0 tree (davi:1.2583) BUG#28386
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of davi. When davi does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-12-21 08:49:53-02:00, davi@stripped +5 -0
  Bug#28386 the general log is incomplete
  
  The problem is that the commands COM_STMT_CLOSE, COM_STMT_RESET,
  COM_STMT_SEND_LONG_DATA, COM_PING and COM_REFRESH (detailed)
  weren't being logged to the general log, which prevents more
  detailed debugging and analysis of the server.
  
  The solution is to log the general log the aforementioned
  commands, detailing the commands arguments where it matters.

  mysys/mf_iocache2.c@stripped, 2007-12-21 08:49:51-02:00, davi@stripped +8 -7
    Don't call my_b_write if there is no bytes to write.

  sql/sql_class.cc@stripped, 2007-12-21 08:49:51-02:00, davi@stripped +1 -0
    Zero initialize name length.

  sql/sql_parse.cc@stripped, 2007-12-21 08:49:52-02:00, davi@stripped +40 -1
    Write to the general log PING commands and detail the
    REFRESH command.

  sql/sql_prepare.cc@stripped, 2007-12-21 08:49:52-02:00, davi@stripped +29 -2
    Log COM_STMT_CLOSE, COM_STMT_RESET and COM_STMT_SEND_LONG_DATA
    to the general log if not inside a stored procedure.

  tests/mysql_client_test.c@stripped, 2007-12-21 08:49:52-02:00, davi@stripped +100 -7
    Add test case for Bug#28386

diff -Nrup a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
--- a/mysys/mf_iocache2.c	2007-01-22 10:10:36 -02:00
+++ b/mysys/mf_iocache2.c	2007-12-21 08:49:51 -02:00
@@ -253,7 +253,7 @@ uint my_b_vprintf(IO_CACHE *info, const 
   uint out_length=0;
   uint minimum_width; /* as yet unimplemented */
   uint minimum_width_sign;
-  uint precision; /* as yet unimplemented for anything but %b */
+  uint precision;
 
   /*
     Store the location of the beginning of a format directive, for the
@@ -295,7 +295,7 @@ uint my_b_vprintf(IO_CACHE *info, const 
     /* Skip if max size is used (to be compatible with printf) */
     while (*fmt == '-') { fmt++; minimum_width_sign= -1; }
     if (*fmt == '*') {
-      precision= (int) va_arg(args, int);
+      precision= va_arg(args, uint);
       fmt++;
     } else {
       while (my_isdigit(&my_charset_latin1, *fmt)) {
@@ -308,7 +308,7 @@ uint my_b_vprintf(IO_CACHE *info, const 
     if (*fmt == '.') {
       fmt++;
       if (*fmt == '*') {
-        precision= (int) va_arg(args, int);
+        precision= va_arg(args, uint);
         fmt++;
       } else {
         while (my_isdigit(&my_charset_latin1, *fmt)) {
@@ -317,21 +317,22 @@ uint my_b_vprintf(IO_CACHE *info, const 
         }
       }
     }
+    else
+      precision= ~0;
 
     if (*fmt == 's')				/* String parameter */
     {
       reg2 char *par = va_arg(args, char *);
-      uint length2 = (uint) strlen(par);
-      /* TODO: implement minimum width and precision */
+      uint length2 = (uint) strnlen(par, precision);
       out_length+= length2;
-      if (my_b_write(info, par, length2))
+      if (length2 && my_b_write(info, par, length2))
 	goto err;
     }
     else if (*fmt == 'b')                       /* Sized buffer parameter, only precision makes sense */
     {
       char *par = va_arg(args, char *);
       out_length+= precision;
-      if (my_b_write(info, par, precision))
+      if (precision && my_b_write(info, par, precision))
         goto err;
     }
     else if (*fmt == 'd' || *fmt == 'u')	/* Integer parameter */
diff -Nrup a/sql/sql_class.cc b/sql/sql_class.cc
--- a/sql/sql_class.cc	2007-11-20 14:14:49 -02:00
+++ b/sql/sql_class.cc	2007-12-21 08:49:51 -02:00
@@ -1739,6 +1739,7 @@ Statement::Statement(LEX *lex_arg, MEM_R
   cursor(0)
 {
   name.str= NULL;
+  name.length= 0;
 }
 
 
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc	2007-12-10 09:19:46 -02:00
+++ b/sql/sql_parse.cc	2007-12-21 08:49:52 -02:00
@@ -782,6 +782,44 @@ static void reset_mqh(LEX_USER *lu, bool
 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
 }
 
+static void log_refresh_cmd(THD *thd, ulong options)
+{
+  char buff[512];
+  String str(buff,(uint32) sizeof(buff), system_charset_info);
+  static struct {
+    ulong option;
+    const char *str;
+  } const refresh_opt[]= {
+    { REFRESH_GRANT, "PRIVILEGES, " },
+    { REFRESH_LOG, "LOGS, " },
+    { REFRESH_TABLES, "TABLES, " },
+    { REFRESH_HOSTS, "HOSTS, " },
+    { REFRESH_STATUS, "STATUS, " },
+    { REFRESH_THREADS, "THREADS, " },
+    { REFRESH_SLAVE, "SLAVE, " },
+    { REFRESH_MASTER, "MASTER, " },
+    { REFRESH_READ_LOCK, "TABLES WITH READ LOCK, " },
+    { REFRESH_QUERY_CACHE, "QUERY CACHE, " },
+    { REFRESH_QUERY_CACHE_FREE, "QUERY CACHE FREE, " },
+    { REFRESH_DES_KEY_FILE, "DES_KEY_FILE, " },
+    { REFRESH_USER_RESOURCES, "USER_RESOURCES, " }
+  };
+
+  str.length(0);
+
+  for (uint i= 0; i < array_elements(refresh_opt); i++)
+  {
+    if (refresh_opt[i].option & options)
+      str.append(refresh_opt[i].str);
+  }
+
+  if (str.is_empty())
+    mysql_log.write(thd, thd->command, NullS);
+  else
+    mysql_log.write(thd, thd->command, "%.*s",
+                    str.length() - 2, str.c_ptr_quick());
+}
+
 void thd_init_client_charset(THD *thd, uint cs_number)
 {
   /*
@@ -2079,7 +2117,7 @@ bool dispatch_command(enum enum_server_c
     ulong options= (ulong) (uchar) packet[0];
     if (check_global_access(thd,RELOAD_ACL))
       break;
-    mysql_log.write(thd,command,NullS);
+    log_refresh_cmd(thd, options);
     if (!reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, &not_used))
       send_ok(thd);
     break;
@@ -2159,6 +2197,7 @@ bool dispatch_command(enum enum_server_c
   }
   case COM_PING:
     statistic_increment(thd->status_var.com_other, &LOCK_status);
+    mysql_log.write(thd, command, NullS);
     send_ok(thd);				// Tell client we are alive
     break;
   case COM_PROCESS_INFO:
diff -Nrup a/sql/sql_prepare.cc b/sql/sql_prepare.cc
--- a/sql/sql_prepare.cc	2007-11-19 14:59:43 -02:00
+++ b/sql/sql_prepare.cc	2007-12-21 08:49:52 -02:00
@@ -2458,6 +2458,11 @@ void mysql_stmt_reset(THD *thd, char *pa
 
   stmt->state= Query_arena::PREPARED;
 
+  /* Don't print if inside a stored procedure. */
+  if (thd->spcont == NULL)
+    mysql_log.write(thd, thd->command, "[%lu] %.*s", stmt->id,
+                    stmt->name.length, stmt->name.str);
+
   send_ok(thd);
 
   DBUG_VOID_RETURN;
@@ -2543,6 +2548,8 @@ void mysql_stmt_get_longdata(THD *thd, c
   uint param_number;
   Prepared_statement *stmt;
   Item_param *param;
+  char *extra_data;
+  ulong extra_length;
 #ifndef EMBEDDED_LIBRARY
   char *packet_end= packet + packet_length - 1;
 #endif
@@ -2582,15 +2589,29 @@ void mysql_stmt_get_longdata(THD *thd, c
   param= stmt->param_array[param_number];
 
 #ifndef EMBEDDED_LIBRARY
-  if (param->set_longdata(packet, (ulong) (packet_end - packet)))
+  extra_data= packet;
+  extra_length= (ulong) (packet_end - packet);
 #else
-  if (param->set_longdata(thd->extra_data, thd->extra_length))
+  extra_data= thd->extra_data;
+  extra_length= thd->extra_length;
 #endif
+
+  if (param->set_longdata(extra_data, extra_length))
   {
     stmt->state= Query_arena::ERROR;
     stmt->last_errno= ER_OUTOFMEMORY;
     sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0);
   }
+
+  /* Don't print if inside a stored procedure. */
+  if (thd->spcont == NULL)
+  {
+    const char fmt[]= "[%lu] %.*s %.*b";
+    mysql_log.write(thd, thd->command, fmt, stmt->id,
+                    stmt->name.length, stmt->name.str,
+                    extra_length, extra_data);
+  }
+
   DBUG_VOID_RETURN;
 }
 
@@ -3064,6 +3085,12 @@ bool Prepared_statement::deallocate()
     my_error(ER_PS_NO_RECURSION, MYF(0));
     return TRUE;
   }
+
+  /* Don't print if inside a stored procedure. */
+  if (thd->spcont == NULL)
+    mysql_log.write(thd, thd->command, "[%lu] %.*s", id,
+                    name.length, name.str);
+
   /* Statement map calls delete stmt on erase */
   thd->stmt_map.erase(this);
   return FALSE;
diff -Nrup a/tests/mysql_client_test.c b/tests/mysql_client_test.c
--- a/tests/mysql_client_test.c	2007-12-01 07:12:28 -02:00
+++ b/tests/mysql_client_test.c	2007-12-21 08:49:52 -02:00
@@ -15037,6 +15037,21 @@ static void test_bug15613()
   mysql_stmt_close(stmt);
 }
 
+static FILE *open_master_log(void)
+{
+  FILE *log_file;
+  char *master_log_filename;
+
+  master_log_filename = (char *) malloc(strlen(opt_vardir) + strlen("/log/master.log") + 1);
+  strcpy(master_log_filename, opt_vardir);
+  strcat(master_log_filename, "/log/master.log");
+  printf("Opening '%s'\n", master_log_filename);
+  log_file= my_fopen(master_log_filename, (int) (O_RDONLY | O_BINARY), MYF(MY_WME));
+  free(master_log_filename);
+
+  return log_file;
+}
+
 /*
   Bug#17667: An attacker has the opportunity to bypass query logging.
 
@@ -15067,7 +15082,6 @@ static void test_bug17667()
 
   struct buffer_and_length *statement_cursor;
   FILE *log_file;
-  char *master_log_filename;
 
   myheader("test_bug17667");
 
@@ -15109,12 +15123,7 @@ static void test_bug17667()
   rc= mysql_query(mysql, "flush logs");
   myquery(rc);
 
-  master_log_filename = (char *) malloc(strlen(opt_vardir) + strlen("/log/master.log") + 1);
-  strcpy(master_log_filename, opt_vardir);
-  strcat(master_log_filename, "/log/master.log");
-  printf("Opening '%s'\n", master_log_filename);
-  log_file= my_fopen(master_log_filename, (int) (O_RDONLY | O_BINARY), MYF(MY_WME));
-  free(master_log_filename);
+  log_file= open_master_log();
 
   if (log_file != NULL) {
 
@@ -16152,6 +16161,89 @@ static void test_bug31669()
   DBUG_VOID_RETURN;
 }
 
+
+/**
+  Bug#28386 the general log is incomplete
+*/
+
+static void test_bug28386()
+{
+  int rc;
+  uint i;
+  MYSQL_STMT *stmt;
+  FILE *log_file;
+  char buffer[MAX_TEST_QUERY_LENGTH*2], *line;
+  struct {
+    const char *str;
+    size_t len;
+    int found;
+  } tokens[] = {
+    { "Close stmt", 0, 0 },
+    { "Reset stmt", 0, 0 },
+    { "Long Data", 0, 0 },
+    { "Ping", 0, 0 },
+    { "Refresh", 0, 0 },
+    { "PRIVILEGES, STATUS", 0, 0 }
+  };
+  DBUG_ENTER("test_bug28386");
+  myheader("test_bug28386");
+
+  sleep(30);
+
+  for (i= 0; i < array_elements(tokens); i++)
+    tokens[i].len= strlen(tokens[i].str);
+
+  stmt= mysql_simple_prepare(mysql, "SELECT 1");
+  check_stmt(stmt);
+
+  rc= mysql_stmt_execute(stmt);
+  check_execute(stmt, rc);
+
+  rc= my_process_stmt_result(stmt);
+  DIE_UNLESS(rc == 1);
+
+  rc= mysql_stmt_reset(stmt);
+  check_execute(stmt, rc);
+
+  rc= mysql_stmt_close(stmt);
+  DIE_UNLESS(!rc);
+
+  rc= mysql_ping(mysql);
+  DIE_UNLESS(!rc);
+
+  mysql_refresh(mysql, REFRESH_GRANT);
+  mysql_refresh(mysql, REFRESH_STATUS | REFRESH_GRANT);
+
+  log_file= open_master_log();
+
+  if (log_file == NULL)
+  {
+    fprintf(stderr, "Could not find the log file, VARDIR/log/master.log, so "
+            "test_bug28386 is \ninconclusive.  Run test from the "
+            "mysql-test/mysql-test-run* program \nto set up the correct "
+            "environment for this test.\n\n");
+    DBUG_VOID_RETURN;
+  }
+
+  while ((line= fgets(buffer, MAX_TEST_QUERY_LENGTH*2, log_file)))
+  {
+    for (i= 0; i < array_elements(tokens); i++)
+    {
+      if (my_memmem(line, MAX_TEST_QUERY_LENGTH*2, tokens[i].str,
+                    tokens[i].len))
+        tokens[i].found= 1;
+    }
+  }
+
+  for (i= 0; i < array_elements(tokens); i++)
+    DIE_UNLESS(tokens[i].found == 1);
+
+  my_fclose(log_file, MYF(0));
+
+  DBUG_VOID_RETURN;
+}
+
+
 /*
   Read and parse arguments and MySQL options from my.cnf
 */
@@ -16446,6 +16538,7 @@ static struct my_tests_st my_tests[]= {
   { "test_bug29948", test_bug29948 },
   { "test_bug29306", test_bug29306 },
   { "test_bug31669", test_bug31669 },
+  { "test_bug28386", test_bug28386 },
   { 0, 0 }
 };
 
Thread
bk commit into 5.0 tree (davi:1.2583) BUG#28386Davi Arnaut21 Dec
  • Re: bk commit into 5.0 tree (davi:1.2583) BUG#28386Konstantin Osipov20 Feb
    • Re: bk commit into 5.0 tree (davi:1.2583) BUG#28386Davi Arnaut20 Feb