Commit 61ac8324 authored by unknown's avatar unknown
Browse files

row0mysql.c, pars0pars.c, eval0eval.c, dict0load.c, dict0dict.c, dict0crea.c:

  Fix bug #3478: InnoDB's FOREIGN KEY tables treated table and database names as case-insensitive; RENAME TABLE t to T would hang in an endless loop if t had a foreign key constraint defined on it
dict0dict.c:
  Fix bug #3478: InnoDB's FOREIGN KEY tables treated table and database names as case-insensitive; RENAME TABLE t to T would hang in an endless loop if t had a foreign key constraint defined on it; fix also a hang that would occur if one tried in ALTER TABLE or RENAME TABLE to create a foreign key constraint name that collided with another existing name


innobase/dict/dict0crea.c:
  Fix bug #3478: InnoDB's FOREIGN KEY tables treated table and database names as case-insensitive; RENAME TABLE t to T would hang in an endless loop if t had a foreign key constraint defined on it
innobase/dict/dict0load.c:
  Fix bug #3478: InnoDB's FOREIGN KEY tables treated table and database names as case-insensitive; RENAME TABLE t to T would hang in an endless loop if t had a foreign key constraint defined on it
innobase/dict/dict0dict.c:
  Fix bug #3478: InnoDB's FOREIGN KEY tables treated table and database names as case-insensitive; RENAME TABLE t to T would hang in an endless loop if t had a foreign key constraint defined on it; fix also a hang that would occur if one tried in ALTER TABLE or RENAME TABLE to create a foreign key constraint name that collided with another existing name
innobase/eval/eval0eval.c:
  Fix bug #3478: InnoDB's FOREIGN KEY tables treated table and database names as case-insensitive; RENAME TABLE t to T would hang in an endless loop if t had a foreign key constraint defined on it
innobase/pars/pars0pars.c:
  Fix bug #3478: InnoDB's FOREIGN KEY tables treated table and database names as case-insensitive; RENAME TABLE t to T would hang in an endless loop if t had a foreign key constraint defined on it
innobase/row/row0mysql.c:
  Fix bug #3478: InnoDB's FOREIGN KEY tables treated table and database names as case-insensitive; RENAME TABLE t to T would hang in an endless loop if t had a foreign key constraint defined on it
parent 99b76e6b
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -1011,6 +1011,12 @@ dict_create_or_check_foreign_constraint_tables(void)
	there are 2 secondary indexes on SYS_FOREIGN, and they
	are defined just like below */
	
	/* NOTE: when designing InnoDB's foreign key support in 2001, we made
	an error and made the table names and the foreign key id of type
	'CHAR' (internally, really a VARCHAR). We should have made the type
	VARBINARY, like in other InnoDB system tables, to get a clean
	design. */

	str = (char *)
	"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
	"BEGIN\n"
@@ -1230,6 +1236,14 @@ dict_create_add_foreigns_to_dictionary(
			" (Note that internally InnoDB adds 'databasename/'\n"
			"in front of the user-defined constraint name).\n",
			ef);
		fputs("Note that InnoDB's FOREIGN KEY system tables store\n"
		      "constraint names as case-insensitive, with the\n"
		      "MySQL standard latin1_swedish_ci collation. If you\n"
		      "create tables or databases whose names differ only in\n"
		      "the character case, then collisions in constraint\n"
		      "names can occur. Workaround: name your constraints\n"
		      "explicitly with unique names.\n",
			ef);

		mutex_exit(&dict_foreign_err_mutex);

+2 −2
Original line number Diff line number Diff line
@@ -132,7 +132,7 @@ dict_index_build_internal_non_clust(
	dict_index_t*	index);	/* in: user representation of a non-clustered
				index */	
/**************************************************************************
Removes a foreign constraint struct from the dictionet cache. */
Removes a foreign constraint struct from the dictionary cache. */
static
void
dict_foreign_remove_from_cache(
@@ -581,7 +581,7 @@ dict_table_get_on_id(
	dict_table_t*	table;
	
	if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
	   || trx->dict_operation) {
	   || trx->dict_operation_lock_mode == RW_X_LATCH) {
		/* It is a system table which will always exist in the table
		cache: we avoid acquiring the dictionary mutex, because
		if we are doing a rollback to handle an error in TABLE
+18 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ Created 4/24/1996 Heikki Tuuri
#include "mach0data.h"
#include "dict0dict.h"
#include "dict0boot.h"
#include "rem0cmp.h"

/************************************************************************
Finds the first table name in the given database. */
@@ -1121,13 +1122,27 @@ dict_load_foreigns(
	rec = btr_pcur_get_rec(&pcur);
	field = rec_get_nth_field(rec, 0, &len);

	/* Check if the table name in record is the one searched for */
	if (len != ut_strlen(table_name)
	    || 0 != ut_memcmp(field, table_name, len)) {
	/* Check if the table name in the record is the one searched for; the
	following call does the comparison in the latin1_swedish_ci
	charset-collation, in a case-insensitive way. */

	if (0 != cmp_data_data(dfield_get_type(dfield),
			dfield_get_data(dfield), dfield_get_len(dfield),
			field, len)) {
		
		goto load_next_index;
	}

	/* Since table names in SYS_FOREIGN are stored in a case-insensitive
	order, we have to check that the table name matches also in a binary
	string comparison. On Unix, MySQL allows table names that only differ
	in character case. */

	if (0 != ut_memcmp(field, table_name, len)) {

		goto next_rec;
	}
		
	if (rec_get_deleted_flag(rec)) {

		goto next_rec;
+17 −1
Original line number Diff line number Diff line
@@ -627,7 +627,11 @@ eval_concat(
}

/*********************************************************************
Evaluates a predefined function node. */
Evaluates a predefined function node. If the first argument is an integer,
this function looks at the second argument which is the integer length in
bytes, and converts the integer to a VARCHAR.
If the first argument is of some other type, this function converts it to
BINARY. */
UNIV_INLINE
void
eval_to_binary(
@@ -638,12 +642,24 @@ eval_to_binary(
	que_node_t*	arg2;
	dfield_t*	dfield;
	byte*		str1;
	ulint		len;
	ulint		len1;

	arg1 = func_node->args;

	str1 = dfield_get_data(que_node_get_val(arg1));

	if (dtype_get_mtype(que_node_get_data_type(arg1)) != DATA_INT) {

		len = dfield_get_len(que_node_get_val(arg1));

		dfield = que_node_get_val(func_node);

		dfield_set_data(dfield, str1, len);

		return;
	}

	arg2 = que_node_get_next(arg1);
	
	len1 = (ulint)eval_node_get_int_val(arg2);
+6 −2
Original line number Diff line number Diff line
@@ -259,9 +259,13 @@ pars_resolve_func_data_type(
		dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
							DATA_ENGLISH, 0, 0);
	} else if (func == PARS_TO_BINARY_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);
		if (dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT) {
			dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
							DATA_ENGLISH, 0, 0);
		} else {
			dtype_set(que_node_get_data_type(node), DATA_BINARY,
								0, 0, 0);
		}
	} else if (func == PARS_TO_NUMBER_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg))
							== DATA_VARCHAR);
Loading