mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
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).
This commit is contained in:
@@ -2077,8 +2077,11 @@ dict_foreign_find_index(
|
||||
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 @@ dict_foreign_find_index(
|
||||
|
||||
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 @@ dict_foreign_add_to_cache(
|
||||
/*======================*/
|
||||
/* 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 @@ dict_foreign_add_to_cache(
|
||||
}
|
||||
|
||||
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 @@ dict_foreign_add_to_cache(
|
||||
}
|
||||
|
||||
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 @@ col_loop1:
|
||||
/* 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 @@ try_find_index:
|
||||
|
||||
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);
|
||||
|
||||
@@ -1094,7 +1094,7 @@ dict_load_foreign(
|
||||
/* 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 @@ dict_load_foreign(
|
||||
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 @@ dict_load_foreigns(
|
||||
/*===============*/
|
||||
/* 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 @@ loop:
|
||||
|
||||
/* 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);
|
||||
|
||||
@@ -197,7 +197,8 @@ dict_foreign_add_to_cache(
|
||||
/*======================*/
|
||||
/* 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. */
|
||||
|
||||
|
||||
@@ -82,7 +82,8 @@ dict_load_foreigns(
|
||||
/*===============*/
|
||||
/* 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. */
|
||||
|
||||
@@ -182,7 +182,7 @@ Creates a temporary file. */
|
||||
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
|
||||
|
||||
@@ -24,7 +24,8 @@ cmp_types_are_equal(
|
||||
/* 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. */
|
||||
|
||||
@@ -34,6 +34,12 @@ extern ibool srv_lower_case_table_names;
|
||||
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 */
|
||||
|
||||
|
||||
@@ -98,7 +98,8 @@ cmp_types_are_equal(
|
||||
/* 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 @@ cmp_types_are_equal(
|
||||
/* 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)
|
||||
|
||||
@@ -522,7 +522,7 @@ row_ins_cascade_calc_update_vec(
|
||||
&& 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 @@ row_ins_cascade_calc_update_vec(
|
||||
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;
|
||||
|
||||
@@ -1804,7 +1804,7 @@ row_table_add_foreign_constraints(
|
||||
|
||||
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 @@ row_rename_table_for_mysql(
|
||||
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 @@ row_rename_table_for_mysql(
|
||||
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 @@ row_rename_table_for_mysql(
|
||||
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 @@ row_rename_table_for_mysql(
|
||||
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 @@ row_rename_table_for_mysql(
|
||||
goto funct_exit;
|
||||
}
|
||||
|
||||
err = dict_load_foreigns(new_name, trx->check_foreigns);
|
||||
/* 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);
|
||||
|
||||
if (row_is_mysql_tmp_table_name(old_name)) {
|
||||
if (err != DB_SUCCESS) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
/* 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 (old_is_tmp) {
|
||||
fputs(" InnoDB: Error: in ALTER TABLE ",
|
||||
stderr);
|
||||
ut_print_name(stderr, trx, new_name);
|
||||
@@ -3237,36 +3238,23 @@ row_rename_table_for_mysql(
|
||||
"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:
|
||||
|
||||
@@ -334,6 +334,12 @@ mutex_t srv_innodb_monitor_mutex;
|
||||
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;
|
||||
|
||||
@@ -1178,6 +1178,13 @@ NetWare. */
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ innobase_shutdown_for_mysql(void)
|
||||
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 */
|
||||
|
||||
@@ -1722,3 +1722,35 @@ checksum table test_checksum;
|
||||
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;
|
||||
|
||||
@@ -1280,4 +1280,53 @@ connection a;
|
||||
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
|
||||
|
||||
123
sql/ha_innodb.cc
123
sql/ha_innodb.cc
@@ -4729,6 +4729,7 @@ ha_innobase::update_table_comment(
|
||||
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 @@ ha_innobase::update_table_comment(
|
||||
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;
|
||||
}
|
||||
|
||||
/* allocate buffer for the full string, and
|
||||
read the contents of the temporary file */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
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 */
|
||||
|
||||
str = my_malloc(length + flen + 3, MYF(0));
|
||||
|
||||
if (str) {
|
||||
char* pos = str + length;
|
||||
if (length) {
|
||||
memcpy(str, comment, length);
|
||||
*pos++ = ';';
|
||||
*pos++ = ' ';
|
||||
}
|
||||
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 @@ ha_innobase::get_foreign_key_create_info(void)
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
|
||||
char* str = 0;
|
||||
long flen;
|
||||
|
||||
ut_a(prebuilt != NULL);
|
||||
|
||||
@@ -4811,47 +4813,42 @@ ha_innobase::get_foreign_key_create_info(void)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* allocate buffer for the string, and
|
||||
read the contents of the temporary file */
|
||||
|
||||
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));
|
||||
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 */
|
||||
|
||||
str = my_malloc(flen + 1, 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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user