summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <monty@mysql.com>2004-11-09 04:06:44 +0200
committerunknown <monty@mysql.com>2004-11-09 04:06:44 +0200
commite0bf844c8ac4cd1efc9547637baac5201775a1c7 (patch)
treea936b651bfe5aa74bd01c17224531d16117c29d9 /innobase
parent20c82f5c014e9902f234f925a218895f3b91b154 (diff)
parentdb67626196992923be83c12302d03cad35cf80f9 (diff)
downloadmariadb-git-e0bf844c8ac4cd1efc9547637baac5201775a1c7.tar.gz
merge on pull
BitKeeper/etc/logging_ok: auto-union BitKeeper/deleted/.del-Makefile.am: Delete: Docs/Images/Makefile.am configure.in: Auto merged innobase/include/row0mysql.h: Auto merged innobase/lock/lock0lock.c: Auto merged innobase/row/row0mysql.c: Auto merged mysql-test/r/ps.result: Auto merged mysql-test/t/ps.test: Auto merged sql/ha_innodb.cc: Auto merged sql/ha_innodb.h: Auto merged sql/item.cc: Auto merged sql/item.h: Auto merged sql/mysql_priv.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_prepare.cc: Auto merged sql/table.cc: Auto merged
Diffstat (limited to 'innobase')
-rw-r--r--innobase/dict/dict0crea.c16
-rw-r--r--innobase/dict/dict0dict.c4
-rw-r--r--innobase/dict/dict0load.c35
-rw-r--r--innobase/eval/eval0eval.c18
-rw-r--r--innobase/ibuf/ibuf0ibuf.c6
-rw-r--r--innobase/include/lock0lock.h8
-rw-r--r--innobase/include/row0mysql.h6
-rw-r--r--innobase/lock/lock0lock.c13
-rw-r--r--innobase/pars/pars0pars.c8
-rw-r--r--innobase/row/row0mysql.c29
10 files changed, 124 insertions, 19 deletions
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index 137964b26c1..cbdc0aab53c 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -1067,6 +1067,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 =
"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
"BEGIN\n"
@@ -1284,9 +1290,17 @@ loop:
fputs(".\nA foreign key constraint of name ", ef);
ut_print_name(ef, trx, foreign->id);
fputs("\nalready exists."
- " (Note that internally InnoDB adds 'databasename/'\n"
+ " (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);
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index c3d0d8d9ac1..bc08fc2437e 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -156,7 +156,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(
@@ -606,7 +606,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
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index d430eadc97b..8fc6eb9141e 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -19,7 +19,9 @@ Created 4/24/1996 Heikki Tuuri
#include "mach0data.h"
#include "dict0dict.h"
#include "dict0boot.h"
+#include "rem0cmp.h"
#include "srv0start.h"
+#include "srv0srv.h"
/************************************************************************
Finds the first table name in the given database. */
@@ -123,6 +125,13 @@ dict_print(void)
ulint len;
mtr_t mtr;
+ /* Enlarge the fatal semaphore wait timeout during the InnoDB table
+ monitor printout */
+
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
mutex_enter(&(dict_sys->mutex));
mtr_start(&mtr);
@@ -145,6 +154,12 @@ loop:
mutex_exit(&(dict_sys->mutex));
+ /* Restore the fatal semaphore wait timeout */
+
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
return;
}
@@ -1242,12 +1257,26 @@ loop:
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)) {
diff --git a/innobase/eval/eval0eval.c b/innobase/eval/eval0eval.c
index ebb6cb1b7d9..5b2d1f857b1 100644
--- a/innobase/eval/eval0eval.c
+++ b/innobase/eval/eval0eval.c
@@ -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);
diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index b3c8ade2414..2191cdc0ee6 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -2866,6 +2866,8 @@ ibuf_delete_rec(
#ifdef UNIV_IBUF_DEBUG
ibuf_count_set(space, page_no, ibuf_count_get(space, page_no) - 1);
+#else
+ UT_NOT_USED(space);
#endif
ibuf_data_sizes_update(ibuf_data, root, mtr);
@@ -3267,11 +3269,11 @@ leave_loop:
ibuf_data->n_merged_recs += n_inserts;
mutex_exit(&ibuf_mutex);
-
+ /*
fprintf(stderr,
"InnoDB: Discarded %lu ibuf entries for space %lu\n",
(ulong) n_inserts, (ulong) space);
-
+ */
ibuf_exit();
mem_heap_free(heap);
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index 9f525042dcc..f8435e14d97 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -463,6 +463,14 @@ lock_rec_hash(
ulint space, /* in: space */
ulint page_no);/* in: page number */
/*************************************************************************
+Gets the table covered by an IX table lock. */
+
+dict_table_t*
+lock_get_ix_table(
+/*==============*/
+ /* out: the table covered by the lock */
+ lock_t* lock); /* in: table lock */
+/*************************************************************************
Checks that a transaction id is sensible, i.e., not in the future. */
ibool
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 581f1bcade3..d4634482752 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -175,8 +175,12 @@ int
row_lock_table_for_mysql(
/*=====================*/
/* out: error code or DB_SUCCESS */
- row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL
+ row_prebuilt_t* prebuilt, /* in: prebuilt struct in the MySQL
table handle */
+ dict_table_t* table); /* in: table to LOCK_IX, or NULL
+ if prebuilt->table should be
+ locked as LOCK_TABLE_EXP |
+ prebuilt->select_lock_type */
/*************************************************************************
Does an insert for MySQL. */
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 44eee53212a..98def88fa31 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -395,6 +395,19 @@ lock_rec_get_nth_bit(
return(ut_bit_get_nth(b, bit_index));
}
+/*************************************************************************
+Gets the table covered by an IX table lock. */
+
+dict_table_t*
+lock_get_ix_table(
+/*==============*/
+ /* out: the table covered by the lock */
+ lock_t* lock) /* in: table lock */
+{
+ ut_a(lock->type_mode == (LOCK_TABLE | LOCK_IX));
+ return(lock->un_member.tab_lock.table);
+}
+
/*************************************************************************/
#define lock_mutex_enter_kernel() mutex_enter(&kernel_mutex)
diff --git a/innobase/pars/pars0pars.c b/innobase/pars/pars0pars.c
index 846cb060a7e..16d630dd318 100644
--- a/innobase/pars/pars0pars.c
+++ b/innobase/pars/pars0pars.c
@@ -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);
- dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
+ 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);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 9ca0b7306fc..6ac8c943dc6 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -779,8 +779,12 @@ int
row_lock_table_for_mysql(
/*=====================*/
/* out: error code or DB_SUCCESS */
- row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL
+ row_prebuilt_t* prebuilt, /* in: prebuilt struct in the MySQL
table handle */
+ dict_table_t* table) /* in: table to LOCK_IX, or NULL
+ if prebuilt->table should be
+ locked as LOCK_TABLE_EXP |
+ prebuilt->select_lock_type */
{
trx_t* trx = prebuilt->trx;
que_thr_t* thr;
@@ -813,8 +817,12 @@ run_again:
trx_start_if_not_started(trx);
- err = lock_table(LOCK_TABLE_EXP, prebuilt->table,
- prebuilt->select_lock_type, thr);
+ if (table) {
+ err = lock_table(0, table, LOCK_IX, thr);
+ } else {
+ err = lock_table(LOCK_TABLE_EXP, prebuilt->table,
+ prebuilt->select_lock_type, thr);
+ }
trx->error_state = err;
@@ -2365,7 +2373,8 @@ row_drop_table_for_mysql(
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
- " WHERE FOR_NAME = table_name;\n"
+ " WHERE FOR_NAME = table_name\n"
+ " AND TO_BINARY(FOR_NAME) = TO_BINARY(table_name);\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE"
@@ -2820,7 +2829,8 @@ row_rename_table_for_mysql(
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
- " WHERE FOR_NAME = old_table_name;\n"
+ " WHERE FOR_NAME = old_table_name\n"
+ " AND TO_BINARY(FOR_NAME) = TO_BINARY(old_table_name);\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
@@ -2853,7 +2863,8 @@ row_rename_table_for_mysql(
" END IF;\n"
"END LOOP;\n"
"UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n"
- "WHERE REF_NAME = old_table_name;\n";
+ "WHERE REF_NAME = old_table_name\n"
+ " AND TO_BINARY(REF_NAME) = TO_BINARY(old_table_name);\n";
static const char str5[] =
"END;\n";
@@ -3063,7 +3074,11 @@ row_rename_table_for_mysql(
if (err != DB_SUCCESS) {
if (err == DB_DUPLICATE_KEY) {
ut_print_timestamp(stderr);
- fputs(" InnoDB: Error: table ", stderr);
+ fputs(
+ " InnoDB: Error; possible reasons:\n"
+ "InnoDB: 1) Table rename would cause two FOREIGN KEY constraints\n"
+ "InnoDB: to have the same internal name in case-insensitive comparison.\n"
+ "InnoDB: 2) table ", stderr);
ut_print_name(stderr, trx, new_name);
fputs(" exists in the InnoDB internal data\n"
"InnoDB: dictionary though MySQL is trying rename table ", stderr);