List:Commits« Previous MessageNext Message »
From:Alex Ivanov Date:December 12 2005 6:07pm
Subject:bk commit into 4.1 tree (aivanov:1.2488) BUG#12071
View as plain text  
Below is the list of changes that have just been committed into a local
4.1 repository of alexi. When alexi 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
  1.2488 05/12/12 21:06:59 aivanov@stripped +16 -0
  Fix BUG#12071: "Windows hang: 'Opening tables' or 'Waiting for
   table' lockup".
   Changes from the innodb-4.1-ss11 snapshot.
   Do not call os_file-create_tmpfile() at runtime. Instead, create
   a tempfile at startup and guard access to it with a mutex.
   Also, fix bugs:
   10511: "Wrong padding of UCS2 CHAR columns in ON UPDATE CASCADE";
   13778: "If FOREIGN_KEY_CHECKS=0, one can create inconsistent FOREIGN
   KEYs". When FOREIGN_KEY_CHECKS=0 we still need to check that
   datatypes between foreign key references are compatible.
   Also, added test cases (also for bug 9802).

  sql/ha_innodb.cc
    1.212 05/12/12 21:06:52 aivanov@stripped +53 -56
    Changes from the innodb-4.1-ss11 snapshot

  mysql-test/t/innodb.test
    1.77 05/12/12 21:06:52 aivanov@stripped +49 -0
    Changes from the innodb-4.1-ss11 snapshot

  mysql-test/r/innodb.result
    1.106 05/12/12 21:06:52 aivanov@stripped +32 -0
    Changes from the innodb-4.1-ss11 snapshot

  libmysqld/ha_blackhole.cc
    1.2 05/12/12 21:06:52 aivanov@stripped +0 -0
    Changes from the innodb-4.1-ss11 snapshot

  innobase/srv/srv0start.c
    1.80 05/12/12 21:06:52 aivanov@stripped +13 -1
    Changes from the innodb-4.1-ss11 snapshot

  innobase/srv/srv0srv.c
    1.79 05/12/12 21:06:52 aivanov@stripped +6 -0
    Changes from the innodb-4.1-ss11 snapshot

  innobase/row/row0mysql.c
    1.93 05/12/12 21:06:52 aivanov@stripped +26 -38
    Changes from the innodb-4.1-ss11 snapshot

  innobase/row/row0ins.c
    1.56 05/12/12 21:06:52 aivanov@stripped +34 -34
    Changes from the innodb-4.1-ss11 snapshot

  innobase/rem/rem0cmp.c
    1.24 05/12/12 21:06:52 aivanov@stripped +6 -5
    Changes from the innodb-4.1-ss11 snapshot

  innobase/include/srv0srv.h
    1.45 05/12/12 21:06:52 aivanov@stripped +6 -0
    Changes from the innodb-4.1-ss11 snapshot

  innobase/include/rem0cmp.h
    1.5 05/12/12 21:06:52 aivanov@stripped +2 -1
    Changes from the innodb-4.1-ss11 snapshot

  innobase/include/os0file.h
    1.36 05/12/12 21:06:52 aivanov@stripped +1 -1
    Changes from the innodb-4.1-ss11 snapshot

  innobase/include/dict0load.h
    1.7 05/12/12 21:06:51 aivanov@stripped +2 -1
    Changes from the innodb-4.1-ss11 snapshot

  innobase/include/dict0dict.h
    1.33 05/12/12 21:06:51 aivanov@stripped +2 -1
    Changes from the innodb-4.1-ss11 snapshot

  innobase/dict/dict0load.c
    1.33 05/12/12 21:06:51 aivanov@stripped +5 -4
    Changes from the innodb-4.1-ss11 snapshot

  innobase/dict/dict0dict.c
    1.65 05/12/12 21:06:51 aivanov@stripped +13 -21
    Changes from the innodb-4.1-ss11 snapshot

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	aivanov
# Host:	mysql.creware.com
# Root:	/home/alexi/innodb-ss/mysql-4.1-ss11

--- 1.1/libmysqld/ha_blackhole.cc	2005-12-12 21:07:11 +03:00
+++ 1.2/libmysqld/ha_blackhole.cc	2005-12-12 21:07:11 +03:00
@@ -1 +1 @@
-SYMLINK -> ./../sql/ha_blackhole.cc
+SYMLINK -> ../sql/ha_blackhole.cc

--- 1.64/innobase/dict/dict0dict.c	2005-04-27 03:56:43 +04:00
+++ 1.65/innobase/dict/dict0dict.c	2005-12-12 21:06:51 +03:00
@@ -2077,8 +2077,11 @@
 	dict_table_t*	table,	/* in: table */
 	const char**	columns,/* in: array of column names */
 	ulint		n_cols,	/* in: number of columns */
-	dict_index_t*	types_idx)/* in: NULL or an index to whose types the
-				column types must match */
+	dict_index_t*	types_idx, /* in: NULL or an index to whose types the
+				   column types must match */
+	ibool		check_charsets)	/* in: whether to check charsets.
+					only has an effect if types_idx !=
+					NULL. */
 {
 	dict_index_t*	index;
 	const char*	col_name;
@@ -2107,7 +2110,8 @@
 
 				if (types_idx && !cmp_types_are_equal(
 				     dict_index_get_nth_type(index, i),
-				     dict_index_get_nth_type(types_idx, i))) {
+				     dict_index_get_nth_type(types_idx, i),
+				     check_charsets)) {
 
 				  	break;
 				}		
@@ -2178,7 +2182,8 @@
 /*======================*/
 					/* out: DB_SUCCESS or error code */
 	dict_foreign_t*	foreign,	/* in, own: foreign key constraint */
-	ibool		check_types)	/* in: TRUE=check type compatibility */
+	ibool		check_charsets)	/* in: TRUE=check charset
+					compatibility */
 {
 	dict_table_t*	for_table;
 	dict_table_t*	ref_table;
@@ -2214,16 +2219,10 @@
 	}
 
 	if (for_in_cache->referenced_table == NULL && ref_table) {
-		dict_index_t*	types_idx;
-		if (check_types) {
-			types_idx = for_in_cache->foreign_index;
-		} else {
-			types_idx = NULL;
-		}
 		index = dict_foreign_find_index(ref_table,
 			(const char**) for_in_cache->referenced_col_names,
 			for_in_cache->n_fields,
-			types_idx);
+			for_in_cache->foreign_index, check_charsets);
 
 		if (index == NULL) {
 			dict_foreign_error_report(ef, for_in_cache,
@@ -2247,16 +2246,10 @@
 	}
 
 	if (for_in_cache->foreign_table == NULL && for_table) {
-		dict_index_t*	types_idx;
-		if (check_types) {
-			types_idx = for_in_cache->referenced_index;
-		} else {
-			types_idx = NULL;
-		}
 		index = dict_foreign_find_index(for_table,
 			(const char**) for_in_cache->foreign_col_names,
 			for_in_cache->n_fields,
-			types_idx);
+			for_in_cache->referenced_index, check_charsets);
 
 		if (index == NULL) {
 			dict_foreign_error_report(ef, for_in_cache,
@@ -3033,7 +3026,7 @@
 	/* Try to find an index which contains the columns
 	as the first fields and in the right order */
 
-	index = dict_foreign_find_index(table, column_names, i, NULL);
+	index = dict_foreign_find_index(table, column_names, i, NULL, TRUE);
 
 	if (!index) {
 		mutex_enter(&dict_foreign_err_mutex);
@@ -3298,8 +3291,7 @@
 
 	if (referenced_table) {
 		index = dict_foreign_find_index(referenced_table,
-						column_names, i,
-						foreign->foreign_index);
+			column_names, i, foreign->foreign_index, TRUE);
 		if (!index) {
 			dict_foreign_free(foreign);
 			mutex_enter(&dict_foreign_err_mutex);

--- 1.32/innobase/dict/dict0load.c	2005-04-12 17:12:27 +04:00
+++ 1.33/innobase/dict/dict0load.c	2005-12-12 21:06:51 +03:00
@@ -1094,7 +1094,7 @@
 				/* out: DB_SUCCESS or error code */
 	const char*	id,	/* in: foreign constraint id as a
 				null-terminated string */
-	ibool		check_types)/* in: TRUE=check type compatibility */
+	ibool		check_charsets)/* in: TRUE=check charset compatibility */
 {	
 	dict_foreign_t*	foreign;
 	dict_table_t*	sys_foreign;
@@ -1205,7 +1205,7 @@
 	a new foreign key constraint but loading one from the data
 	dictionary. */
 
-	return(dict_foreign_add_to_cache(foreign, check_types));
+	return(dict_foreign_add_to_cache(foreign, check_charsets));
 }
 
 /***************************************************************************
@@ -1220,7 +1220,8 @@
 /*===============*/
 					/* out: DB_SUCCESS or error code */
 	const char*	table_name,	/* in: table name */
-	ibool		check_types)	/* in: TRUE=check type compatibility */
+	ibool		check_charsets)	/* in: TRUE=check charset
+					compatibility */
 {
 	btr_pcur_t	pcur;
 	mem_heap_t* 	heap;
@@ -1319,7 +1320,7 @@
 
 	/* Load the foreign constraint definition to the dictionary cache */
 	
-	err = dict_load_foreign(id, check_types);
+	err = dict_load_foreign(id, check_charsets);
 
 	if (err != DB_SUCCESS) {
 		btr_pcur_close(&pcur);

--- 1.32/innobase/include/dict0dict.h	2005-04-27 03:56:30 +04:00
+++ 1.33/innobase/include/dict0dict.h	2005-12-12 21:06:51 +03:00
@@ -197,7 +197,8 @@
 /*======================*/
 					/* out: DB_SUCCESS or error code */
 	dict_foreign_t*	foreign,	/* in, own: foreign key constraint */
-	ibool		check_types);	/* in: TRUE=check type compatibility */
+	ibool		check_charsets);/* in: TRUE=check charset
+					compatibility */
 /*************************************************************************
 Checks if a table is referenced by foreign keys. */
 

--- 1.6/innobase/include/dict0load.h	2005-04-12 17:12:27 +04:00
+++ 1.7/innobase/include/dict0load.h	2005-12-12 21:06:51 +03:00
@@ -82,7 +82,8 @@
 /*===============*/
 					/* out: DB_SUCCESS or error code */
 	const char*	table_name,	/* in: table name */
-	ibool		check_types);	/* in: TRUE=check type compatibility */
+	ibool		check_charsets);/* in: TRUE=check charsets
+					compatibility */
 /************************************************************************
 Prints to the standard output information on all tables found in the data
 dictionary system table. */

--- 1.35/innobase/include/os0file.h	2005-07-26 15:03:26 +04:00
+++ 1.36/innobase/include/os0file.h	2005-12-12 21:06:52 +03:00
@@ -182,7 +182,7 @@
 FILE*
 os_file_create_tmpfile(void);
 /*========================*/
-			/* out: temporary file handle (never NULL) */
+			/* out: temporary file handle, or NULL on error */
 /***************************************************************************
 The os_file_opendir() function opens a directory stream corresponding to the
 directory named by the dirname argument. The directory stream is positioned

--- 1.4/innobase/include/rem0cmp.h	2003-06-15 01:57:10 +04:00
+++ 1.5/innobase/include/rem0cmp.h	2005-12-12 21:06:52 +03:00
@@ -24,7 +24,8 @@
 				/* out: TRUE if the types are considered
 				equal in comparisons */
 	dtype_t*	type1,	/* in: type 1 */
-	dtype_t*	type2);	/* in: type 2 */
+	dtype_t*	type2,	/* in: type 2 */
+	ibool		check_charsets); /* in: whether to check charsets */
 /*****************************************************************
 This function is used to compare two data fields for which we know the
 data type. */

--- 1.44/innobase/include/srv0srv.h	2005-04-19 15:31:59 +04:00
+++ 1.45/innobase/include/srv0srv.h	2005-12-12 21:06:52 +03:00
@@ -34,6 +34,12 @@
 extern mutex_t	srv_monitor_file_mutex;
 /* Temporary file for innodb monitor output */
 extern FILE*	srv_monitor_file;
+/* Mutex for locking srv_dict_tmpfile.
+This mutex has a very high rank; threads reserving it should not
+be holding any InnoDB latches. */
+extern mutex_t	srv_dict_tmpfile_mutex;
+/* Temporary file for output from the data dictionary */
+extern FILE*	srv_dict_tmpfile;
 
 /* Server parameters which are read from the initfile */
 

--- 1.23/innobase/rem/rem0cmp.c	2005-03-07 13:03:27 +03:00
+++ 1.24/innobase/rem/rem0cmp.c	2005-12-12 21:06:52 +03:00
@@ -98,7 +98,8 @@
 				/* out: TRUE if the types are considered
 				equal in comparisons */
 	dtype_t*	type1,	/* in: type 1 */
-	dtype_t*	type2)	/* in: type 2 */
+	dtype_t*	type2,	/* in: type 2 */
+	ibool		check_charsets) /* in: whether to check charsets */
 {
 	if (dtype_is_non_binary_string_type(type1->mtype, type1->prtype)
 	    && dtype_is_non_binary_string_type(type2->mtype, type2->prtype)) {
@@ -106,12 +107,12 @@
 		/* Both are non-binary string types: they can be compared if
 		and only if the charset-collation is the same */
 
-		if (dtype_get_charset_coll(type1->prtype)
-				== dtype_get_charset_coll(type2->prtype)) {
+		if (check_charsets) {
+			return(dtype_get_charset_coll(type1->prtype)
+			    == dtype_get_charset_coll(type2->prtype));
+		} else {
 			return(TRUE);
 		}
-
-		return(FALSE);
         }
 
 	if (dtype_is_binary_string_type(type1->mtype, type1->prtype)

--- 1.55/innobase/row/row0ins.c	2005-10-28 17:15:52 +04:00
+++ 1.56/innobase/row/row0ins.c	2005-12-12 21:06:52 +03:00
@@ -522,7 +522,7 @@
 				    && ufield->new_val.len
 				       < dtype_get_fixed_size(type)) {
 
-                                        ulint cset;
+					ulint	cset;
 
 				        ufield->new_val.data =
 						mem_heap_alloc(heap,
@@ -530,42 +530,42 @@
 					ufield->new_val.len = 
 						dtype_get_fixed_size(type);
 
-                                        /* Handle UCS2 strings differently.
-                                        As no new collations will be
-                                        introduced in 4.1, we hardcode the
-                                        charset-collation codes here.
-                                        In 5.0, the logic is based on
-                                        mbminlen. */
-                                        cset = dtype_get_charset_coll(
-                                          dtype_get_prtype(type));
+					/* Handle UCS2 strings differently.
+					As no new collations will be
+					introduced in 4.1, we hardcode the
+					charset-collation codes here.
+					In 5.0, the logic is based on
+					mbminlen. */
+					cset = dtype_get_charset_coll(
+						dtype_get_prtype(type));
 
-                                        if (cset == 35/*ucs2_general_ci*/
-                                            || cset == 90/*ucs2_bin*/
-                                            || (cset >= 128/*ucs2_unicode_ci*/
-                                          && cset <= 144
-                                          /*ucs2_persian_ci*/)) {
-                                          /* space=0x0020 */
-                                          ulint i;
-                                          for (i = 0;
-                                               i < ufield->new_val.len;
-                                               i += 2) {
-                                            mach_write_to_2(((byte*)
-                                              ufield->new_val.data)
-                                              + i, 0x0020);
-                                          }
-                                        } else {
-                                          ut_a(dtype_get_pad_char(type)
-                                              != ULINT_UNDEFINED);
+					if (cset == 35/*ucs2_general_ci*/
+					    || cset == 90/*ucs2_bin*/
+					    || (cset >= 128/*ucs2_unicode_ci*/
+						&& cset <= 144
+						/*ucs2_persian_ci*/)) {
+						/* space=0x0020 */
+						ulint	i;
+						for (i = 0;
+						     i < ufield->new_val.len;
+						     i += 2) {
+						    mach_write_to_2(((byte*)
+							ufield->new_val.data)
+							+ i, 0x0020);
+						}
+					} else {
+						ut_a(dtype_get_pad_char(type)
+						    != ULINT_UNDEFINED);
 
-                                          memset(ufield->new_val.data,
-                                              (byte)dtype_get_pad_char(
-                                                type),
-                                              ufield->new_val.len);
-                                        }
+						memset(ufield->new_val.data,
+						    (byte)dtype_get_pad_char(
+									type),
+						    ufield->new_val.len);
+					}
 
-                                        memcpy(ufield->new_val.data,
-                                          parent_ufield->new_val.data,
-                                          parent_ufield->new_val.len);
+					memcpy(ufield->new_val.data,
+						parent_ufield->new_val.data,
+						parent_ufield->new_val.len);
 				}
 
 				ufield->extern_storage = FALSE;

--- 1.92/innobase/row/row0mysql.c	2005-05-26 16:57:15 +04:00
+++ 1.93/innobase/row/row0mysql.c	2005-12-12 21:06:52 +03:00
@@ -1804,7 +1804,7 @@
 
 	if (err == DB_SUCCESS) {
 		/* Check that also referencing constraints are ok */
-		err = dict_load_foreigns(name, trx->check_foreigns);
+		err = dict_load_foreigns(name, TRUE);
 	}
 
 	if (err != DB_SUCCESS) {
@@ -2963,7 +2963,8 @@
 	mem_heap_t*	heap			= NULL;
 	const char**	constraints_to_drop	= NULL;
 	ulint		n_constraints_to_drop	= 0;
-        ibool           recovering_temp_table   = FALSE;
+	ibool           recovering_temp_table   = FALSE;
+	ibool		old_is_tmp, new_is_tmp;
 	ulint		len;
 	ulint		i;
         ibool		success;
@@ -3003,6 +3004,9 @@
 	trx->op_info = "renaming table";
 	trx_start_if_not_started(trx);
 
+	old_is_tmp = row_is_mysql_tmp_table_name(old_name);
+	new_is_tmp = row_is_mysql_tmp_table_name(new_name);
+	
 	if (row_mysql_is_recovered_tmp_table(new_name)) {
 
                 recovering_temp_table = TRUE;
@@ -3047,7 +3051,7 @@
 	len = (sizeof str1) + (sizeof str2) + (sizeof str3) + (sizeof str5) - 4
 		+ ut_strlenq(new_name, '\'') + ut_strlenq(old_name, '\'');
 
-	if (row_is_mysql_tmp_table_name(new_name)) {
+	if (new_is_tmp) {
 		db_name_len = dict_get_db_name_len(old_name) + 1;
 
 		/* MySQL is doing an ALTER TABLE command and it renames the
@@ -3200,7 +3204,7 @@
 		the table is stored in a single-table tablespace */
 
 		success = dict_table_rename_in_cache(table, new_name,
-				!row_is_mysql_tmp_table_name(new_name));
+				!new_is_tmp);
 		if (!success) {
 			trx->error_state = DB_SUCCESS;
 			trx_general_rollback_for_mysql(trx, FALSE, NULL);
@@ -3217,19 +3221,16 @@
 			goto funct_exit;
 		}
 
-		err = dict_load_foreigns(new_name, trx->check_foreigns);
-
-		if (row_is_mysql_tmp_table_name(old_name)) {
+		/* We only want to switch off some of the type checking in
+		an ALTER, not in a RENAME. */
+		
+		err = dict_load_foreigns(new_name,
+			old_is_tmp ? trx->check_foreigns : TRUE);
 
-			/* MySQL is doing an ALTER TABLE command and it
-			renames the created temporary table to the name
-			of the original table. In the ALTER TABLE we maybe
-			created some FOREIGN KEY constraints for the temporary
-			table. But we want to load also the foreign key
-			constraint definitions for the original table name. */
+		if (err != DB_SUCCESS) {
+			ut_print_timestamp(stderr);
 
-			if (err != DB_SUCCESS) {
-	    			ut_print_timestamp(stderr);
+			if (old_is_tmp) {
 				fputs("  InnoDB: Error: in ALTER TABLE ",
 					stderr);
 				ut_print_name(stderr, trx, new_name);
@@ -3237,36 +3238,23 @@
 	"InnoDB: has or is referenced in foreign key constraints\n"
 	"InnoDB: which are not compatible with the new table definition.\n",
 					stderr);
-
-				ut_a(dict_table_rename_in_cache(table,
-					old_name, FALSE));
-				trx->error_state = DB_SUCCESS;
-				trx_general_rollback_for_mysql(trx, FALSE,
-									NULL);
-				trx->error_state = DB_SUCCESS;
-			}
-		} else {
-			if (err != DB_SUCCESS) {
-
-	    			ut_print_timestamp(stderr);
-
+			} else {
 				fputs(
 				"  InnoDB: Error: in RENAME TABLE table ",
 					stderr);
 				ut_print_name(stderr, trx, new_name);
 				fputs("\n"
-     "InnoDB: is referenced in foreign key constraints\n"
-     "InnoDB: which are not compatible with the new table definition.\n",
+	"InnoDB: is referenced in foreign key constraints\n"
+	"InnoDB: which are not compatible with the new table definition.\n",
 					stderr);
-     
-				ut_a(dict_table_rename_in_cache(table,
-					old_name, FALSE));
-						
-				trx->error_state = DB_SUCCESS;
-				trx_general_rollback_for_mysql(trx, FALSE,
-									NULL);
-				trx->error_state = DB_SUCCESS;
 			}
+
+			ut_a(dict_table_rename_in_cache(table,
+					old_name, FALSE));
+			trx->error_state = DB_SUCCESS;
+			trx_general_rollback_for_mysql(trx, FALSE,
+				NULL);
+			trx->error_state = DB_SUCCESS;
 		}
 	}
 funct_exit:	

--- 1.78/innobase/srv/srv0srv.c	2005-04-19 15:32:18 +04:00
+++ 1.79/innobase/srv/srv0srv.c	2005-12-12 21:06:52 +03:00
@@ -334,6 +334,12 @@
 mutex_t	srv_monitor_file_mutex;
 /* Temporary file for innodb monitor output */
 FILE*	srv_monitor_file;
+/* Mutex for locking srv_dict_tmpfile.
+This mutex has a very high rank; threads reserving it should not
+be holding any InnoDB latches. */
+mutex_t	srv_dict_tmpfile_mutex;
+/* Temporary file for output from the data dictionary */
+FILE*	srv_dict_tmpfile;
 
 ulint	srv_main_thread_process_no	= 0;
 ulint	srv_main_thread_id		= 0;

--- 1.79/innobase/srv/srv0start.c	2005-08-12 09:54:43 +04:00
+++ 1.80/innobase/srv/srv0start.c	2005-12-12 21:06:52 +03:00
@@ -1178,6 +1178,13 @@
 		}
 	}
 
+	mutex_create(&srv_dict_tmpfile_mutex);
+	mutex_set_level(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
+	srv_dict_tmpfile = os_file_create_tmpfile();
+	if (!srv_dict_tmpfile) {
+		return(DB_ERROR);
+	}
+
 	/* Restrict the maximum number of file i/o threads */
 	if (srv_n_file_io_threads > SRV_MAX_N_IO_THREADS) {
 
@@ -1804,8 +1811,13 @@
 			mem_free(srv_monitor_file_name);
 		}
 	}
-	
+	if (srv_dict_tmpfile) {
+		fclose(srv_dict_tmpfile);
+		srv_dict_tmpfile = 0;
+	}
+
 	mutex_free(&srv_monitor_file_mutex);
+	mutex_free(&srv_dict_tmpfile_mutex);
 
 	/* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside
 	them */

--- 1.105/mysql-test/r/innodb.result	2005-09-28 15:14:40 +04:00
+++ 1.106/mysql-test/r/innodb.result	2005-12-12 21:06:52 +03:00
@@ -1722,3 +1722,35 @@
 Table	Checksum
 test.test_checksum	2050879373
 drop table test_checksum;
+set foreign_key_checks=0;
+create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb;
+create table t1(a char(10) primary key, b varchar(20)) engine = innodb;
+ERROR HY000: Can't create table './test/t1.frm' (errno: 150)
+set foreign_key_checks=1;
+drop table t2;
+set foreign_key_checks=0;
+create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8;
+ERROR HY000: Can't create table './test/t2.frm' (errno: 150)
+set foreign_key_checks=1;
+drop table t1;
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb;
+create table t1(a varchar(10) primary key) engine = innodb;
+alter table t1 modify column a int;
+Got one of the listed errors
+set foreign_key_checks=1;
+drop table t2,t1;
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
+create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
+alter table t1 convert to character set utf8;
+set foreign_key_checks=1;
+drop table t2,t1;
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
+create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
+rename table t3 to t1;
+ERROR HY000: Error on rename of './test/t3' to './test/t1' (errno: 150)
+set foreign_key_checks=1;
+drop table t2,t3;

--- 1.76/mysql-test/t/innodb.test	2005-09-28 15:14:40 +04:00
+++ 1.77/mysql-test/t/innodb.test	2005-12-12 21:06:52 +03:00
@@ -1280,4 +1280,53 @@
 checksum table test_checksum;
 drop table test_checksum;
 
+# tests for bugs #9802 and #13778
+
+# test that FKs between invalid types are not accepted
+
+set foreign_key_checks=0;
+create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb;
+-- error 1005
+create table t1(a char(10) primary key, b varchar(20)) engine = innodb;
+set foreign_key_checks=1;
+drop table t2;
+
+# test that FKs between different charsets are not accepted in CREATE even
+# when f_k_c is 0
+
+set foreign_key_checks=0;
+create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
+-- error 1005
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8;
+set foreign_key_checks=1;
+drop table t1;
+
+# test that invalid datatype conversions with ALTER are not allowed
+
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb;
+create table t1(a varchar(10) primary key) engine = innodb;
+-- error 1025,1025
+alter table t1 modify column a int;
+set foreign_key_checks=1;
+drop table t2,t1;
+
+# test that charset conversions with ALTER are allowed when f_k_c is 0
+
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
+create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
+alter table t1 convert to character set utf8;
+set foreign_key_checks=1;
+drop table t2,t1;
+
+# test that RENAME does not allow invalid charsets when f_k_c is 0
+
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
+create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
+-- error 1025
+rename table t3 to t1;
+set foreign_key_checks=1;
+drop table t2,t3;
 # End of 4.1 tests

--- 1.211/sql/ha_innodb.cc	2005-10-03 18:54:30 +04:00
+++ 1.212/sql/ha_innodb.cc	2005-12-12 21:06:52 +03:00
@@ -4729,6 +4729,7 @@
 	uint	length			= strlen(comment);
 	char*				str;
 	row_prebuilt_t*	prebuilt	= (row_prebuilt_t*)innobase_prebuilt;
+	long	flen;
 
 	/* We do not know if MySQL can call this function before calling
 	external_lock(). To be safe, update the thd of the current table
@@ -4748,43 +4749,43 @@
 	trx_search_latch_release_if_reserved(prebuilt->trx);
 	str = NULL;
 
-	if (FILE* file = os_file_create_tmpfile()) {
-		long	flen;
+	/* output the data to a temporary file */
 
-		/* output the data to a temporary file */
-		fprintf(file, "InnoDB free: %lu kB",
+	mutex_enter_noninline(&srv_dict_tmpfile_mutex);
+	rewind(srv_dict_tmpfile);
+
+	fprintf(srv_dict_tmpfile, "InnoDB free: %lu kB",
       		   (ulong) fsp_get_available_space_in_free_extents(
       					prebuilt->table->space));
 
-		dict_print_info_on_foreign_keys(FALSE, file,
+	dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
 				prebuilt->trx, prebuilt->table);
-		flen = ftell(file);
-		if (flen < 0) {
-			flen = 0;
-		} else if (length + flen + 3 > 64000) {
-			flen = 64000 - 3 - length;
-		}
+	flen = ftell(srv_dict_tmpfile);
+	if (flen < 0) {
+		flen = 0;
+	} else if (length + flen + 3 > 64000) {
+		flen = 64000 - 3 - length;
+	}
 
-		/* allocate buffer for the full string, and
-		read the contents of the temporary file */
+	/* allocate buffer for the full string, and
+	read the contents of the temporary file */
 
-		str = my_malloc(length + flen + 3, MYF(0));
+	str = my_malloc(length + flen + 3, MYF(0));
 
-		if (str) {
-			char* pos	= str + length;
-			if(length) {
-				memcpy(str, comment, length);
-				*pos++ = ';';
-				*pos++ = ' ';
-			}
-			rewind(file);
-			flen = fread(pos, 1, flen, file);
-			pos[flen] = 0;
+	if (str) {
+		char* pos	= str + length;
+		if (length) {
+			memcpy(str, comment, length);
+			*pos++ = ';';
+			*pos++ = ' ';
 		}
-
-		fclose(file);
+		rewind(srv_dict_tmpfile);
+		flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
+		pos[flen] = 0;
 	}
 
+	mutex_exit_noninline(&srv_dict_tmpfile_mutex);
+
         prebuilt->trx->op_info = (char*)"";
 
   	return(str ? str : (char*) comment);
@@ -4802,6 +4803,7 @@
 {
 	row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
 	char*	str	= 0;
+	long	flen;
 
 	ut_a(prebuilt != NULL);
 
@@ -4811,46 +4813,41 @@
 
 	update_thd(current_thd);
 
-	if (FILE* file = os_file_create_tmpfile()) {
-		long	flen;
+	prebuilt->trx->op_info = (char*)"getting info on foreign keys";
 
-		prebuilt->trx->op_info = (char*)"getting info on foreign keys";
+	/* In case MySQL calls this in the middle of a SELECT query,
+	release possible adaptive hash latch to avoid
+	deadlocks of threads */
 
-		/* In case MySQL calls this in the middle of a SELECT query,
-		release possible adaptive hash latch to avoid
-		deadlocks of threads */
+	trx_search_latch_release_if_reserved(prebuilt->trx);
 
-		trx_search_latch_release_if_reserved(prebuilt->trx);
+	mutex_enter_noninline(&srv_dict_tmpfile_mutex);
+	rewind(srv_dict_tmpfile);
 
-		/* output the data to a temporary file */
-		dict_print_info_on_foreign_keys(TRUE, file,
+	/* output the data to a temporary file */
+	dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
 				prebuilt->trx, prebuilt->table);
-		prebuilt->trx->op_info = (char*)"";
+	prebuilt->trx->op_info = (char*)"";
 
-		flen = ftell(file);
-		if (flen < 0) {
-			flen = 0;
-		} else if(flen > 64000 - 1) {
-			flen = 64000 - 1;
-		}
+	flen = ftell(srv_dict_tmpfile);
+	if (flen < 0) {
+		flen = 0;
+	} else if (flen > 64000 - 1) {
+		flen = 64000 - 1;
+	}
 
-		/* allocate buffer for the string, and
-		read the contents of the temporary file */
+	/* allocate buffer for the string, and
+	read the contents of the temporary file */
 
-		str = my_malloc(flen + 1, MYF(0));
+	str = my_malloc(flen + 1, MYF(0));
 
-		if (str) {
-			rewind(file);
-			flen = fread(str, 1, flen, file);
-			str[flen] = 0;
-		}
-
-		fclose(file);
-	} else {
-		/* unable to create temporary file */
-          	str = my_strdup(
-"/* Error: cannot display foreign key constraints */", MYF(0));
+	if (str) {
+		rewind(srv_dict_tmpfile);
+		flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
+		str[flen] = 0;
 	}
+
+	mutex_exit_noninline(&srv_dict_tmpfile_mutex);
 
   	return(str);
 }
Thread
bk commit into 4.1 tree (aivanov:1.2488) BUG#12071Alex Ivanov12 Dec