List:Commits« Previous MessageNext Message »
From:vasil.dimov Date:January 17 2012 10:19am
Subject:bzr push into mysql-trunk branch (vasil.dimov:3738 to 3739) Bug#13432465
View as plain text  
 3739 Vasil Dimov	2012-01-17
      Fix Bug#13432465 "INNODB: IGNORING STRANGE ROW FROM MYSQL.INNODB_INDEX_STATS"
      IN MYSQLD ERROR LOG
      
      There are two problems related to this bug report:
      
      1. InnoDB persistent storage tables mysql.innodb_table_stats and
      mysql.innodb_index_stats have been working case-insensitively until now wrt
      their contents (and we store table and index names in VARCHAR() columns in
      those tables) because they are created with options
      "ENGINE=INNODB DEFAULT CHARSET=utf8" while it should be
      "ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin"
      in order to be case-sensitive.
      
      Due to this, rows for table 'A' from innodb_index_stats could have been
      picked while searching for stats for table 'a'.
      
      2. In index name comparison we used the length of the value found in
      innodb_index_stats and thus could have picked "c1" as a value for an index
      named "c10".
      
      The solution is to add COLLATE=utf8_bin to tables' create definitions and
      to also compare lengths in addition to using strncmp().
      
      This patch also touches 3 other places where strncmp/strncasecmp is used -
      we could have picked a row from innodb_index_stats where stat_name='siz'
      when searching for a row where stat_name='size'.
      
      Reviewed by:	Marko (via IM/email)

    modified:
      scripts/mysql_system_tables.sql
      storage/innobase/dict/dict0stats.cc
 3738 Alexander Barkov	2012-01-17
      BUG#13545236 - ASSERT IN SEC_SINCE_EPOCH
      
      Problem:
      WL#946 introduced a new methid Item_cache_datetime::get_date().
      It did not execute check_date(), so in some cases it started
      to return non-NULL result when instead of expected NULL.
      
      Before WL#946 the generic Item::get_date() was used,
      which executes check_date() inside str_to_datetime_with_warn().
      
      Fix:
      adding check_date() in the new method, to reproduce the pre-WL#946 behaviour.
      
      modified:
            mysql-test/r/func_time.result
            mysql-test/t/func_time.test
            sql/item.cc

    modified:
      mysql-test/r/func_time.result
      mysql-test/t/func_time.test
      sql/item.cc
=== modified file 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql	revid:alexander.barkov@stripped
+++ b/scripts/mysql_system_tables.sql	revid:vasil.dimov@stripped
@@ -117,7 +117,7 @@ CREATE TABLE IF NOT EXISTS innodb_table_
 	clustered_index_size		BIGINT UNSIGNED NOT NULL,
 	sum_of_other_index_sizes	BIGINT UNSIGNED NOT NULL,
 	PRIMARY KEY (database_name, table_name)
-) ENGINE=INNODB DEFAULT CHARSET=utf8;
+) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
 
 CREATE TABLE IF NOT EXISTS innodb_index_stats (
 	database_name			VARCHAR(64) NOT NULL,
@@ -135,7 +135,7 @@ CREATE TABLE IF NOT EXISTS innodb_index_
 	PRIMARY KEY (database_name, table_name, index_name, stat_name),
 	FOREIGN KEY (database_name, table_name)
 	  REFERENCES innodb_table_stats (database_name, table_name)
-) ENGINE=INNODB DEFAULT CHARSET=utf8;
+) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
 
 SET SESSION sql_mode=@sql_mode_orig;
 

=== modified file 'storage/innobase/dict/dict0stats.cc'
--- a/storage/innobase/dict/dict0stats.cc	revid:alexander.barkov@stripped
+++ b/storage/innobase/dict/dict0stats.cc	revid:vasil.dimov@stripped
@@ -1910,10 +1910,8 @@ dict_stats_fetch_index_stats_step(
 			     index != NULL;
 			     index = dict_table_get_next_index(index)) {
 
-				// FIXME: Can we use a better cast operator
-				if (strncasecmp(index->name,
-						(const char*) data,
-						len) == 0) {
+				if (strlen(index->name) == len
+				    && memcmp(index->name, data, len) == 0) {
 					/* the corresponding index was found */
 					break;
 				}
@@ -1999,26 +1997,29 @@ dict_stats_fetch_index_stats_step(
 	/* sample_size could be UINT64_UNDEFINED here, if it is NULL */
 
 #define PFX	"n_diff_pfx"
+#define PFX_LEN	10
 
-	if (strncasecmp("size", stat_name, stat_name_len) == 0) {
+	if (stat_name_len == 4 /* strlen("size") */
+	    && strncasecmp("size", stat_name, stat_name_len) == 0) {
 		index->stat_index_size = (ulint) stat_value;
 		arg->stats_were_modified = TRUE;
-	} else if (strncasecmp("n_leaf_pages", stat_name, stat_name_len)
+	} else if (stat_name_len == 12 /* strlen("n_leaf_pages") */
+		   && strncasecmp("n_leaf_pages", stat_name, stat_name_len)
 		   == 0) {
 		index->stat_n_leaf_pages = (ulint) stat_value;
 		arg->stats_were_modified = TRUE;
-	} else if (strncasecmp(PFX, stat_name,
-			       ut_min(strlen(PFX), stat_name_len)) == 0) {
+	} else if (stat_name_len > PFX_LEN /* e.g. stat_name=="n_diff_pfx01" */
+		   && strncasecmp(PFX, stat_name, PFX_LEN) == 0) {
 
 		const char*	num_ptr;
 		unsigned long	n_pfx;
 
 		/* point num_ptr into "1" from "n_diff_pfx12..." */
-		num_ptr = stat_name + strlen(PFX);
+		num_ptr = stat_name + PFX_LEN;
 
 		/* stat_name should have exactly 2 chars appended to PFX
 		and they should be digits */
-		if (stat_name_len != strlen(PFX) + 2
+		if (stat_name_len != PFX_LEN + 2
 		    || num_ptr[0] < '0' || num_ptr[0] > '9'
 		    || num_ptr[1] < '0' || num_ptr[1] > '9') {
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (vasil.dimov:3738 to 3739) Bug#13432465vasil.dimov17 Jan