List:Commits« Previous MessageNext Message »
From:kevin.lewis Date:November 30 2010 7:22pm
Subject:bzr commit into mysql-trunk-innodb branch (kevin.lewis:3345) Bug#55222
View as plain text  
#At file:///Users/kevinlewis/Work/Mysql/55222.push/mysql-trunk-innodb/ based on revid:kevin.lewis@stripped

 3345 kevin.lewis@stripped	2010-11-30 [merge]
      Merge Bug#55222 from mysql-5.5-innodb

    modified:
      mysql-test/r/lowercase_table4.result
      mysql-test/suite/innodb/r/innodb_bug57904.result
      mysql-test/suite/innodb/t/innodb_bug57904.test
      mysql-test/t/lowercase_table4.test
      storage/innobase/dict/dict0dict.c
      storage/innobase/dict/dict0load.c
      storage/innobase/dict/dict0mem.c
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/include/dict0mem.h
      storage/innobase/include/srv0srv.h
      storage/innobase/row/row0ins.c
      storage/innobase/row/row0mysql.c
      storage/innobase/row/row0upd.c
      storage/innobase/srv/srv0srv.c
=== modified file 'mysql-test/r/lowercase_table4.result'
--- a/mysql-test/r/lowercase_table4.result	revid:kevin.lewis@stripped
+++ b/mysql-test/r/lowercase_table4.result	revid:kevin.lewis@stripped
@@ -5,3 +5,111 @@
 CREATE DATABASE XY;
 USE XY;
 DROP DATABASE XY;
+USE TEST;
+#
+# Bug55222 Mysqldump table names case bug in REFERENCES clause
+# InnoDB did not handle lower_case_table_names=2 for
+# foreign_table_names and referenced_table_names.
+#
+SHOW VARIABLES LIKE 'lower_case_table_names';
+Variable_name	Value
+lower_case_table_names	2
+DROP TABLE IF EXISTS `Table2`;
+DROP TABLE IF EXISTS `Table1`;
+CREATE TABLE `Table1`(c1 INT PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE `Table2`(c1 INT PRIMARY KEY, c2 INT) ENGINE=InnoDB;
+ALTER TABLE `Table2` ADD CONSTRAINT fk1 FOREIGN KEY(c2) REFERENCES `Table1`(c1);
+SHOW CREATE TABLE `Table2`;
+Table	Table2
+Create Table	CREATE TABLE `Table2` (
+  `c1` int(11) NOT NULL,
+  `c2` int(11) DEFAULT NULL,
+  PRIMARY KEY (`c1`),
+  KEY `fk1` (`c2`),
+  CONSTRAINT `fk1` FOREIGN KEY (`c2`) REFERENCES `Table1` (`c1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS;
+CONSTRAINT_CATALOG	def
+CONSTRAINT_SCHEMA	test
+CONSTRAINT_NAME	fk1
+UNIQUE_CONSTRAINT_CATALOG	def
+UNIQUE_CONSTRAINT_SCHEMA	test
+UNIQUE_CONSTRAINT_NAME	PRIMARY
+MATCH_OPTION	NONE
+UPDATE_RULE	RESTRICT
+DELETE_RULE	RESTRICT
+TABLE_NAME	Table2
+REFERENCED_TABLE_NAME	Table1
+DROP TABLE `Table2`;
+DROP TABLE `Table1`;
+DROP TABLE IF EXISTS Product_Order;
+DROP TABLE IF EXISTS Product;
+DROP TABLE IF EXISTS Customer;
+CREATE TABLE Product (Category INT NOT NULL, Id INT NOT NULL,
+Price DECIMAL, PRIMARY KEY(Category, Id)) ENGINE=InnoDB;
+CREATE TABLE Customer (Id INT NOT NULL, PRIMARY KEY (Id)) ENGINE=InnoDB;
+CREATE TABLE Product_Order (No INT NOT NULL AUTO_INCREMENT,
+Product_Category INT NOT NULL,
+Product_Id INT NOT NULL,
+Customer_Id INT NOT NULL,
+PRIMARY KEY(No),
+INDEX (Product_Category, Product_Id),
+FOREIGN KEY (Product_Category, Product_Id)
+REFERENCES Product(Category, Id) ON UPDATE CASCADE ON DELETE RESTRICT,
+INDEX (Customer_Id),
+FOREIGN KEY (Customer_Id)
+REFERENCES Customer(Id)
+) ENGINE=INNODB;
+SHOW CREATE TABLE Product_Order;
+Table	Product_Order
+Create Table	CREATE TABLE `Product_Order` (
+  `No` int(11) NOT NULL AUTO_INCREMENT,
+  `Product_Category` int(11) NOT NULL,
+  `Product_Id` int(11) NOT NULL,
+  `Customer_Id` int(11) NOT NULL,
+  PRIMARY KEY (`No`),
+  KEY `Product_Category` (`Product_Category`,`Product_Id`),
+  KEY `Customer_Id` (`Customer_Id`),
+  CONSTRAINT `product_order_ibfk_1` FOREIGN KEY (`Product_Category`, `Product_Id`) REFERENCES `Product` (`Category`, `Id`) ON UPDATE CASCADE,
+  CONSTRAINT `product_order_ibfk_2` FOREIGN KEY (`Customer_Id`) REFERENCES `Customer` (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE Product;
+Table	Product
+Create Table	CREATE TABLE `Product` (
+  `Category` int(11) NOT NULL,
+  `Id` int(11) NOT NULL,
+  `Price` decimal(10,0) DEFAULT NULL,
+  PRIMARY KEY (`Category`,`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE Customer;
+Table	Customer
+Create Table	CREATE TABLE `Customer` (
+  `Id` int(11) NOT NULL,
+  PRIMARY KEY (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS;
+CONSTRAINT_CATALOG	def
+CONSTRAINT_SCHEMA	test
+CONSTRAINT_NAME	product_order_ibfk_1
+UNIQUE_CONSTRAINT_CATALOG	def
+UNIQUE_CONSTRAINT_SCHEMA	test
+UNIQUE_CONSTRAINT_NAME	PRIMARY
+MATCH_OPTION	NONE
+UPDATE_RULE	CASCADE
+DELETE_RULE	RESTRICT
+TABLE_NAME	Product_Order
+REFERENCED_TABLE_NAME	Product
+CONSTRAINT_CATALOG	def
+CONSTRAINT_SCHEMA	test
+CONSTRAINT_NAME	product_order_ibfk_2
+UNIQUE_CONSTRAINT_CATALOG	def
+UNIQUE_CONSTRAINT_SCHEMA	test
+UNIQUE_CONSTRAINT_NAME	PRIMARY
+MATCH_OPTION	NONE
+UPDATE_RULE	RESTRICT
+DELETE_RULE	RESTRICT
+TABLE_NAME	Product_Order
+REFERENCED_TABLE_NAME	Customer
+DROP TABLE Product_Order;
+DROP TABLE Product;
+DROP TABLE Customer;

=== modified file 'mysql-test/suite/innodb/r/innodb_bug57904.result'
--- a/mysql-test/suite/innodb/r/innodb_bug57904.result	revid:kevin.lewis@stripped
+++ b/mysql-test/suite/innodb/r/innodb_bug57904.result	revid:kevin.lewis@stripped
@@ -1,16 +1,16 @@
-CREATE TABLE product (category INT NOT NULL, id INT NOT NULL, 
+CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,
 price DECIMAL, PRIMARY KEY(category, id)) ENGINE=INNODB;
 CREATE TABLE customer (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
-CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT, 
-product_category INT NOT NULL, 
-product_id INT NOT NULL, 
-customer_id INT NOT NULL, 
-PRIMARY KEY(no), 
-INDEX (product_category, product_id), 
-FOREIGN KEY (product_category, product_id) 
-REFERENCES product(category, id) ON UPDATE CASCADE ON DELETE RESTRICT, 
-INDEX (customer_id), 
-FOREIGN KEY (customer_id) 
+CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,
+product_category INT NOT NULL,
+product_id INT NOT NULL,
+customer_id INT NOT NULL,
+PRIMARY KEY(no),
+INDEX (product_category, product_id),
+FOREIGN KEY (product_category, product_id)
+REFERENCES product(category, id) ON UPDATE CASCADE ON DELETE RESTRICT,
+INDEX (customer_id),
+FOREIGN KEY (customer_id)
 REFERENCES customer(id)
 ) ENGINE=INNODB;
 SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS;

=== modified file 'mysql-test/suite/innodb/t/innodb_bug57904.test'
--- a/mysql-test/suite/innodb/t/innodb_bug57904.test	revid:kevin.lewis@stripped
+++ b/mysql-test/suite/innodb/t/innodb_bug57904.test	revid:kevin.lewis@stripped
@@ -3,19 +3,19 @@
 #
 -- source include/have_innodb.inc
 
-CREATE TABLE product (category INT NOT NULL, id INT NOT NULL, 
+CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,
 	price DECIMAL, PRIMARY KEY(category, id)) ENGINE=INNODB;
 CREATE TABLE customer (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
-CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT, 
-	product_category INT NOT NULL, 
-	product_id INT NOT NULL, 
-	customer_id INT NOT NULL, 
-	PRIMARY KEY(no), 
-	INDEX (product_category, product_id), 
-	FOREIGN KEY (product_category, product_id) 
-		REFERENCES product(category, id) ON UPDATE CASCADE ON DELETE RESTRICT, 
-	INDEX (customer_id), 
-	FOREIGN KEY (customer_id) 
+CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,
+	product_category INT NOT NULL,
+	product_id INT NOT NULL,
+	customer_id INT NOT NULL,
+	PRIMARY KEY(no),
+	INDEX (product_category, product_id),
+	FOREIGN KEY (product_category, product_id)
+		REFERENCES product(category, id) ON UPDATE CASCADE ON DELETE RESTRICT,
+	INDEX (customer_id),
+	FOREIGN KEY (customer_id)
 		REFERENCES customer(id)
 	) ENGINE=INNODB;
 

=== modified file 'mysql-test/t/lowercase_table4.test'
--- a/mysql-test/t/lowercase_table4.test	revid:kevin.lewis@stripped
+++ b/mysql-test/t/lowercase_table4.test	revid:kevin.lewis@stripped
@@ -53,4 +53,56 @@ eval SELECT * FROM XY.T_$tcs LIMIT 1;
 --enable_query_log
 --enable_result_log
 DROP DATABASE XY;
+USE TEST;
+
+--echo #
+--echo # Bug55222 Mysqldump table names case bug in REFERENCES clause
+--echo # InnoDB did not handle lower_case_table_names=2 for
+--echo # foreign_table_names and referenced_table_names.
+--echo #
+
+SHOW VARIABLES LIKE 'lower_case_table_names';
+
+--disable_warnings
+DROP TABLE IF EXISTS `Table2`;
+DROP TABLE IF EXISTS `Table1`;
+--disable_warnings
+
+CREATE TABLE `Table1`(c1 INT PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE `Table2`(c1 INT PRIMARY KEY, c2 INT) ENGINE=InnoDB;
+ALTER TABLE `Table2` ADD CONSTRAINT fk1 FOREIGN KEY(c2) REFERENCES `Table1`(c1);
+query_vertical SHOW CREATE TABLE `Table2`;
+query_vertical SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS;
+DROP TABLE `Table2`;
+DROP TABLE `Table1`;
+
+--disable_warnings
+DROP TABLE IF EXISTS Product_Order;
+DROP TABLE IF EXISTS Product;
+DROP TABLE IF EXISTS Customer;
+--enable_warnings
+
+CREATE TABLE Product (Category INT NOT NULL, Id INT NOT NULL,
+	Price DECIMAL, PRIMARY KEY(Category, Id)) ENGINE=InnoDB;
+CREATE TABLE Customer (Id INT NOT NULL, PRIMARY KEY (Id)) ENGINE=InnoDB;
+CREATE TABLE Product_Order (No INT NOT NULL AUTO_INCREMENT,
+	Product_Category INT NOT NULL,
+	Product_Id INT NOT NULL,
+	Customer_Id INT NOT NULL,
+	PRIMARY KEY(No),
+	INDEX (Product_Category, Product_Id),
+	FOREIGN KEY (Product_Category, Product_Id)
+		REFERENCES Product(Category, Id) ON UPDATE CASCADE ON DELETE RESTRICT,
+	INDEX (Customer_Id),
+	FOREIGN KEY (Customer_Id)
+		REFERENCES Customer(Id)
+	) ENGINE=INNODB;
+
+query_vertical SHOW CREATE TABLE Product_Order;
+query_vertical SHOW CREATE TABLE Product;
+query_vertical SHOW CREATE TABLE Customer;
+query_vertical SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS;
+DROP TABLE Product_Order;
+DROP TABLE Product;
+DROP TABLE Customer;
 

=== modified file 'storage/innobase/dict/dict0dict.c'
--- a/storage/innobase/dict/dict0dict.c	revid:kevin.lewis@stripped
+++ b/storage/innobase/dict/dict0dict.c	revid:kevin.lewis@stripped
@@ -54,8 +54,9 @@ UNIV_INTERN dict_index_t*	dict_ind_compa
 #include "que0que.h"
 #include "rem0cmp.h"
 #include "row0merge.h"
+#include "srv0srv.h" /* srv_lower_case_table_names */
 #include "m_ctype.h" /* my_isspace() */
-#include "ha_prototypes.h" /* innobase_strcasecmp() */
+#include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str() */
 #include "srv0mon.h"
 #include "srv0start.h"
 #include "lock0lock.h"
@@ -1412,13 +1413,13 @@ dict_table_rename_in_cache(
 			/* Allocate a longer name buffer;
 			TODO: store buf len to save memory */
 
-			foreign->foreign_table_name
-				= mem_heap_alloc(foreign->heap,
-						 ut_strlen(table->name) + 1);
+			foreign->foreign_table_name = mem_heap_strdup(
+				foreign->heap, table->name);
+			dict_mem_foreign_table_name_lookup_set(foreign, TRUE);
+		} else {
+			strcpy(foreign->foreign_table_name, table->name);
+			dict_mem_foreign_table_name_lookup_set(foreign, FALSE);
 		}
-
-		strcpy(foreign->foreign_table_name, table->name);
-
 		if (strchr(foreign->id, '/')) {
 			ulint	db_len;
 			char*	old_id;
@@ -1484,12 +1485,14 @@ dict_table_rename_in_cache(
 			/* Allocate a longer name buffer;
 			TODO: store buf len to save memory */
 
-			foreign->referenced_table_name = mem_heap_alloc(
-				foreign->heap, strlen(table->name) + 1);
+			foreign->referenced_table_name = mem_heap_strdup(
+				foreign->heap, table->name);
+			dict_mem_referenced_table_name_lookup_set(foreign, TRUE);
+		} else {
+			/* Use the same buffer */
+			strcpy(foreign->referenced_table_name, table->name);
+			dict_mem_referenced_table_name_lookup_set(foreign, FALSE);
 		}
-
-		strcpy(foreign->referenced_table_name, table->name);
-
 		foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
 	}
 
@@ -2964,10 +2967,10 @@ dict_foreign_add_to_cache(
 	ut_ad(mutex_own(&(dict_sys->mutex)));
 
 	for_table = dict_table_check_if_in_cache_low(
-		foreign->foreign_table_name);
+		foreign->foreign_table_name_lookup);
 
 	ref_table = dict_table_check_if_in_cache_low(
-		foreign->referenced_table_name);
+		foreign->referenced_table_name_lookup);
 	ut_a(for_table || ref_table);
 
 	if (for_table) {
@@ -3409,19 +3412,25 @@ dict_scan_table_name(
 	memcpy(ref, database_name, database_name_len);
 	ref[database_name_len] = '/';
 	memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
-#ifndef __WIN__
-	if (srv_lower_case_table_names) {
-#endif /* !__WIN__ */
-		/* The table name is always put to lower case on Windows. */
+
+	/* Values;  0 = Store and compare as given; case sensitive
+	            1 = Store and compare in lower; case insensitive
+	            2 = Store as given, compare in lower; case semi-sensitive */
+	if (srv_lower_case_table_names == 2) {
 		innobase_casedn_str(ref);
-#ifndef __WIN__
+		*table = dict_table_get_low(ref);
+		memcpy(ref, database_name, database_name_len);
+		ref[database_name_len] = '/';
+		memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
+	} else {
+		if (srv_lower_case_table_names == 1) {
+			innobase_casedn_str(ref);
+		}
+		*table = dict_table_get_low(ref);
 	}
-#endif /* !__WIN__ */
 
 	*success = TRUE;
 	*ref_name = ref;
-	*table = dict_table_get_low(ref);
-
 	return(ptr);
 }
 
@@ -3910,8 +3919,10 @@ col_loop1:
 	}
 
 	foreign->foreign_table = table;
-	foreign->foreign_table_name = mem_heap_strdup(foreign->heap,
-						      table->name);
+	foreign->foreign_table_name = mem_heap_strdup(
+		foreign->heap, table->name);
+	dict_mem_foreign_table_name_lookup_set(foreign, TRUE);
+
 	foreign->foreign_index = index;
 	foreign->n_fields = (unsigned int) i;
 	foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
@@ -4168,8 +4179,9 @@ try_find_index:
 	foreign->referenced_index = index;
 	foreign->referenced_table = referenced_table;
 
-	foreign->referenced_table_name
-		= mem_heap_strdup(foreign->heap, referenced_table_name);
+	foreign->referenced_table_name = mem_heap_strdup(
+		foreign->heap, referenced_table_name);
+	dict_mem_referenced_table_name_lookup_set(foreign, TRUE);
 
 	foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
 						       i * sizeof(void*));
@@ -4875,8 +4887,8 @@ dict_print_info_on_foreign_key_in_create
 
 	fputs(") REFERENCES ", file);
 
-	if (dict_tables_have_same_db(foreign->foreign_table_name,
-				     foreign->referenced_table_name)) {
+	if (dict_tables_have_same_db(foreign->foreign_table_name_lookup,
+				     foreign->referenced_table_name_lookup)) {
 		/* Do not print the database name of the referenced table */
 		ut_print_name(file, trx, TRUE,
 			      dict_remove_db_name(

=== modified file 'storage/innobase/dict/dict0load.c'
--- a/storage/innobase/dict/dict0load.c	revid:kevin.lewis@stripped
+++ b/storage/innobase/dict/dict0load.c	revid:kevin.lewis@stripped
@@ -42,6 +42,7 @@ Created 4/24/1996 Heikki Tuuri
 #include "srv0start.h"
 #include "srv0srv.h"
 #include "dict0priv.h"
+#include "ha_prototypes.h" /* innobase_casedn_str() */
 
 
 /** Following are six InnoDB system tables */
@@ -437,6 +438,8 @@ dict_process_sys_fields_rec(
 	return(err_msg);
 
 }
+
+#ifdef FOREIGN_NOT_USED
 /********************************************************************//**
 This function parses a SYS_FOREIGN record and populate a dict_foreign_t
 structure with the information from the record. For detail information
@@ -485,13 +488,16 @@ err_len:
 	}
 	foreign->foreign_table_name = mem_heap_strdupl(
 		heap, (const char*) field, len);
+	dict_mem_foreign_table_name_lookup_set(foreign, TRUE);
 
 	field = rec_get_nth_field_old(rec, 4/*REF_NAME*/, &len);
 	if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
 		goto err_len;
 	}
+
 	foreign->referenced_table_name = mem_heap_strdupl(
 		heap, (const char*) field, len);
+	dict_mem_referenced_table_name_lookup_set(foreign, TRUE);
 
 	field = rec_get_nth_field_old(rec, 5/*N_COLS*/, &len);
 	if (UNIV_UNLIKELY(len != 4)) {
@@ -504,6 +510,9 @@ err_len:
 
 	return(NULL);
 }
+#endif  /* FOREIGN_NOT_USED */
+
+#ifdef FOREIGN_NOT_USED
 /********************************************************************//**
 This function parses a SYS_FOREIGN_COLS record and extract necessary
 information from the record and return to caller.
@@ -567,6 +576,8 @@ err_len:
 
 	return(NULL);
 }
+#endif  /* FOREIGN_NOT_USED */
+
 /********************************************************************//**
 Determine the flags of a table described in SYS_TABLES.
 @return compressed page size in kilobytes; or 0 if the tablespace is
@@ -2062,12 +2073,15 @@ dict_load_foreign(
 	foreign->id = mem_heap_strdup(foreign->heap, id);
 
 	field = rec_get_nth_field_old(rec, 3, &len);
+
 	foreign->foreign_table_name = mem_heap_strdupl(
 		foreign->heap, (char*) field, len);
+	dict_mem_foreign_table_name_lookup_set(foreign, TRUE);
 
 	field = rec_get_nth_field_old(rec, 4, &len);
 	foreign->referenced_table_name = mem_heap_strdupl(
 		foreign->heap, (char*) field, len);
+	dict_mem_referenced_table_name_lookup_set(foreign, TRUE);
 
 	btr_pcur_close(&pcur);
 	mtr_commit(&mtr);
@@ -2075,7 +2089,7 @@ dict_load_foreign(
 	dict_load_foreign_cols(id, foreign);
 
 	ref_table = dict_table_check_if_in_cache_low(
-			foreign->referenced_table_name);
+			foreign->referenced_table_name_lookup);
 
 	/* We could possibly wind up in a deep recursive calls if
 	we call dict_table_get_low() again here if there
@@ -2108,7 +2122,7 @@ dict_load_foreign(
 		have to load it so that we are able to make type comparisons
 		in the next function call. */
 
-		for_table = dict_table_get_low(foreign->foreign_table_name);
+		for_table = dict_table_get_low(foreign->foreign_table_name_lookup);
 
 		if (for_table && ref_table && check_recursive) {
 			/* This is to record the longest chain of ancesters

=== modified file 'storage/innobase/dict/dict0mem.c'
--- a/storage/innobase/dict/dict0mem.c	revid:kevin.lewis@stripped
+++ b/storage/innobase/dict/dict0mem.c	revid:kevin.lewis@stripped
@@ -33,6 +33,7 @@ Created 1/8/1996 Heikki Tuuri
 #include "data0type.h"
 #include "mach0data.h"
 #include "dict0dict.h"
+#include "srv0srv.h" /* srv_lower_case_table_names */
 #ifndef UNIV_HOTBACKUP
 # include "lock0lock.h"
 #endif /* !UNIV_HOTBACKUP */
@@ -288,6 +289,60 @@ dict_mem_foreign_create(void)
 }
 
 /**********************************************************************//**
+Sets the foreign_table_name_lookup pointer based on the value of
+srv_lower_case_table_names.  If that is 0 or 1, foreign_table_name_lookup
+will point to foreign_table_name.  If 2, then another string is allocated
+of the heap and set to lower case. */
+UNIV_INLINE
+void
+dict_mem_foreign_table_name_lookup_set(
+/*===================================*/
+	dict_foreign_t*	foreign,	/*!< in/out: foreign struct */
+	ibool		do_alloc)	/*!< in: is an alloc needed */
+{
+	if (srv_lower_case_table_names == 2) {
+		if (do_alloc) {
+			foreign->foreign_table_name_lookup = mem_heap_alloc(
+				foreign->heap,
+				strlen(foreign->foreign_table_name) + 1);
+		}
+		strcpy(foreign->foreign_table_name_lookup,
+		       foreign->foreign_table_name);
+		innobase_casedn_str(foreign->foreign_table_name_lookup);
+	} else {
+		foreign->foreign_table_name_lookup
+			= foreign->foreign_table_name;
+	}
+}
+
+/**********************************************************************//**
+Sets the referenced_table_name_lookup pointer based on the value of
+srv_lower_case_table_names.  If that is 0 or 1,
+referenced_table_name_lookup will point to referenced_table_name.  If 2,
+then another string is allocated of the heap and set to lower case. */
+UNIV_INLINE
+void
+dict_mem_referenced_table_name_lookup_set(
+/*======================================*/
+	dict_foreign_t*	foreign,	/*!< in/out: foreign struct */
+	ibool		do_alloc)	/*!< in: is an alloc needed */
+{
+	if (srv_lower_case_table_names == 2) {
+		if (do_alloc) {
+			foreign->referenced_table_name_lookup = mem_heap_alloc(
+				foreign->heap,
+				strlen(foreign->referenced_table_name) + 1);
+		}
+		strcpy(foreign->referenced_table_name_lookup,
+		       foreign->referenced_table_name);
+		innobase_casedn_str(foreign->referenced_table_name_lookup);
+	} else {
+		foreign->referenced_table_name_lookup
+			= foreign->referenced_table_name;
+	}
+}
+
+/**********************************************************************//**
 Adds a field definition to an index. NOTE: does not take a copy
 of the column name if the field is a column. The memory occupied
 by the column name may be released only after publishing the index. */

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	revid:kevin.lewis@stripped
+++ b/storage/innobase/handler/ha_innodb.cc	revid:kevin.lewis@stripped
@@ -3846,6 +3846,7 @@ ha_innobase::open(
 	UT_NOT_USED(test_if_locked);
 
 	thd = ha_thd();
+	srv_lower_case_table_names = lower_case_table_names;
 
 	/* Under some cases MySQL seems to call this function while
 	holding btr_search_latch. This breaks the latching order as
@@ -7161,11 +7162,7 @@ ha_innobase::create(
 
 	trx = innobase_trx_allocate(thd);
 
-	if (lower_case_table_names) {
-		srv_lower_case_table_names = TRUE;
-	} else {
-		srv_lower_case_table_names = FALSE;
-	}
+	srv_lower_case_table_names = lower_case_table_names;
 
 	strcpy(name2, name);
 
@@ -7604,11 +7601,7 @@ ha_innobase::delete_table(
 
 	trx = innobase_trx_allocate(thd);
 
-	if (lower_case_table_names) {
-		srv_lower_case_table_names = TRUE;
-	} else {
-		srv_lower_case_table_names = FALSE;
-	}
+	srv_lower_case_table_names = lower_case_table_names;
 
 	name_len = strlen(name);
 
@@ -7727,11 +7720,7 @@ innobase_rename_table(
 	char*	norm_to;
 	char*	norm_from;
 
-	if (lower_case_table_names) {
-		srv_lower_case_table_names = TRUE;
-	} else {
-		srv_lower_case_table_names = FALSE;
-	}
+	srv_lower_case_table_names = lower_case_table_names;
 
 	// Magic number 64 arbitrary
 	norm_to = (char*) my_malloc(strlen(to) + 64, MYF(0));

=== modified file 'storage/innobase/include/dict0mem.h'
--- a/storage/innobase/include/dict0mem.h	revid:kevin.lewis@stripped
+++ b/storage/innobase/include/dict0mem.h	revid:kevin.lewis@stripped
@@ -238,6 +238,26 @@ dict_foreign_t*
 dict_mem_foreign_create(void);
 /*=========================*/
 
+/**********************************************************************//**
+Sets the foreign_table_name_lookup pointer based on the value of
+srv_lower_case_table_names. */
+UNIV_INTERN
+void
+dict_mem_foreign_table_name_lookup_set(
+/*===================================*/
+	dict_foreign_t*	foreign,	/*!< in/out: foreign struct */
+	ibool		do_alloc);	/*!< in: is an alloc needed */
+
+/**********************************************************************//**
+Sets the reference_table_name_lookup pointer based on the value of
+srv_lower_case_table_names. */
+UNIV_INTERN
+void
+dict_mem_referenced_table_name_lookup_set(
+/*======================================*/
+	dict_foreign_t*	foreign,	/*!< in/out: foreign struct */
+	ibool		do_alloc);	/*!< in: is an alloc needed */
+
 /** Data structure for a column in a table */
 struct dict_col_struct{
 	/*----------------------*/
@@ -398,10 +418,14 @@ struct dict_foreign_struct{
 	unsigned	type:6;		/*!< 0 or DICT_FOREIGN_ON_DELETE_CASCADE
 					or DICT_FOREIGN_ON_DELETE_SET_NULL */
 	char*		foreign_table_name;/*!< foreign table name */
+	char*		foreign_table_name_lookup;
+				/*!< foreign table name used for dict lookup */
 	dict_table_t*	foreign_table;	/*!< table where the foreign key is */
 	const char**	foreign_col_names;/*!< names of the columns in the
 					foreign key */
 	char*		referenced_table_name;/*!< referenced table name */
+	char*		referenced_table_name_lookup;
+				/*!< referenced table name for dict lookup*/
 	dict_table_t*	referenced_table;/*!< table where the referenced key
 					is */
 	const char**	referenced_col_names;/*!< names of the referenced

=== modified file 'storage/innobase/include/srv0srv.h'
--- a/storage/innobase/include/srv0srv.h	revid:kevin.lewis@stripped
+++ b/storage/innobase/include/srv0srv.h	revid:kevin.lewis@stripped
@@ -71,8 +71,8 @@ at a time */
 #define SRV_AUTO_EXTEND_INCREMENT	\
 	(srv_auto_extend_increment * ((1024 * 1024) / UNIV_PAGE_SIZE))
 
-/* This is set to TRUE if the MySQL user has set it in MySQL */
-extern ibool	srv_lower_case_table_names;
+/* This is set to the MySQL server value for this variable. */
+extern uint	srv_lower_case_table_names;
 
 /* Mutex for locking srv_monitor_file */
 extern mutex_t	srv_monitor_file_mutex;

=== modified file 'storage/innobase/row/row0ins.c'
--- a/storage/innobase/row/row0ins.c	revid:kevin.lewis@stripped
+++ b/storage/innobase/row/row0ins.c	revid:kevin.lewis@stripped
@@ -1545,7 +1545,7 @@ row_ins_check_foreign_constraints(
 			if (foreign->referenced_table == NULL) {
 
 				ref_table = dict_table_open_on_name(
-					foreign->referenced_table_name, FALSE);
+					foreign->referenced_table_name_lookup, FALSE);
 			}
 
 			if (0 == trx->dict_operation_lock_mode) {

=== modified file 'storage/innobase/row/row0mysql.c'
--- a/storage/innobase/row/row0mysql.c	revid:kevin.lewis@stripped
+++ b/storage/innobase/row/row0mysql.c	revid:kevin.lewis@stripped
@@ -3192,7 +3192,7 @@ check_next_foreign:
 
 	if (foreign && trx->check_foreigns
 	    && !(drop_db && dict_tables_have_same_db(
-			 name, foreign->foreign_table_name))) {
+			 name, foreign->foreign_table_name_lookup))) {
 		FILE*	ef	= dict_foreign_err_file;
 
 		/* We only allow dropping a referenced table if

=== modified file 'storage/innobase/row/row0upd.c'
--- a/storage/innobase/row/row0upd.c	revid:kevin.lewis@stripped
+++ b/storage/innobase/row/row0upd.c	revid:kevin.lewis@stripped
@@ -242,7 +242,7 @@ row_upd_check_references_constraints(
 			if (foreign->foreign_table == NULL) {
 
 				ref_table = dict_table_open_on_name(
-					foreign->foreign_table_name, FALSE);
+					foreign->foreign_table_name_lookup, FALSE);
 			}
 
 			if (foreign->foreign_table) {

=== modified file 'storage/innobase/srv/srv0srv.c'
--- a/storage/innobase/srv/srv0srv.c	revid:kevin.lewis@stripped
+++ b/storage/innobase/srv/srv0srv.c	revid:kevin.lewis@stripped
@@ -69,9 +69,11 @@ Created 10/8/1995 Heikki Tuuri
 #include "mysql/plugin.h"
 #include "mysql/service_thd_wait.h"
 
-/* This is set to TRUE if the MySQL user has set it in MySQL; currently
-affects only FOREIGN KEY definition parsing */
-UNIV_INTERN ibool	srv_lower_case_table_names	= FALSE;
+/* This is set to the MySQL server value for this variable.  It is only
+needed for FOREIGN KEY definition parsing since FOREIGN KEY names are not
+stored in the server metadata. The server stores and enforces it for
+regular database and table names.*/
+UNIV_INTERN uint	srv_lower_case_table_names	= 0;
 
 /* The following is the maximum allowed duration of a lock wait. */
 UNIV_INTERN ulint	srv_fatal_semaphore_wait_threshold = 600;

No bundle (reason: revision is a merge).
Thread
bzr commit into mysql-trunk-innodb branch (kevin.lewis:3345) Bug#55222kevin.lewis30 Nov