summaryrefslogtreecommitdiff
path: root/innobase/dict
diff options
context:
space:
mode:
authorunknown <heikki@hundin.mysql.fi>2002-11-06 00:41:27 +0200
committerunknown <heikki@hundin.mysql.fi>2002-11-06 00:41:27 +0200
commit444d8207d9a277231733dc6cd58bf21b626bba31 (patch)
treefed8334ab45443418d527c3837593e1121ed1975 /innobase/dict
parent23f4865b163293006bbedbc2b69bc55ba1081baa (diff)
downloadmariadb-git-444d8207d9a277231733dc6cd58bf21b626bba31.tar.gz
Many files:
Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock sql/ha_innodb.cc: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/dict/dict0crea.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/dict/dict0dict.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/include/log0recv.h: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/include/row0mysql.h: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/include/srv0srv.h: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/include/trx0trx.h: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/log/log0recv.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/os/os0sync.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/os/os0thread.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/row/row0ins.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/row/row0mysql.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/row/row0purge.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/row/row0undo.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/row/row0upd.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/srv/srv0srv.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/srv/srv0start.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/trx/trx0roll.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/trx/trx0trx.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock
Diffstat (limited to 'innobase/dict')
-rw-r--r--innobase/dict/dict0crea.c18
-rw-r--r--innobase/dict/dict0dict.c219
2 files changed, 199 insertions, 38 deletions
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index 60beeacf435..b0f84e5663a 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -1041,7 +1041,7 @@ dict_create_or_check_foreign_constraint_tables(void)
que_t* graph;
ulint error;
trx_t* trx;
- char* str;
+ char* str;
mutex_enter(&(dict_sys->mutex));
@@ -1060,20 +1060,24 @@ dict_create_or_check_foreign_constraint_tables(void)
return(DB_SUCCESS);
}
+ mutex_exit(&(dict_sys->mutex));
+
trx = trx_allocate_for_mysql();
trx->op_info = (char *) "creating foreign key sys tables";
+ row_mysql_lock_data_dictionary(trx);
+
if (table1) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN table\n");
- row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
}
if (table2) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN_COLS table\n");
- row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);
}
fprintf(stderr,
@@ -1122,8 +1126,8 @@ dict_create_or_check_foreign_constraint_tables(void)
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN tables\n");
- row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
- row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);
error = DB_MUST_GET_MORE_FILE_SPACE;
}
@@ -1132,6 +1136,8 @@ dict_create_or_check_foreign_constraint_tables(void)
trx->op_info = (char *) "";
+ row_mysql_unlock_data_dictionary(trx);
+
trx_free_for_mysql(trx);
if (error == DB_SUCCESS) {
@@ -1139,8 +1145,6 @@ dict_create_or_check_foreign_constraint_tables(void)
"InnoDB: Foreign key constraint system tables created\n");
}
- mutex_exit(&(dict_sys->mutex));
-
return(error);
}
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 2ee2c9d18a9..18f27602cf0 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -30,13 +30,16 @@ Created 1/8/1996 Heikki Tuuri
dict_sys_t* dict_sys = NULL; /* the dictionary system */
rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
- this in X-mode, implicit or backround
+ this in X-mode; implicit or backround
operations purge, rollback, foreign
key checks reserve this in S-mode; we
cannot trust that MySQL protects
implicit or background operations
- from dropping a table: this is our
- mechanism */
+ a table drop since MySQL does not
+ know of them; therefore we need this;
+ NOTE: a transaction which reserves
+ this must keep book on the mode in
+ trx->dict_operation_lock_mode */
#define DICT_HEAP_SIZE 100 /* initial memory heap size when
creating a table or index object */
@@ -183,6 +186,58 @@ dict_foreign_free(
dict_foreign_t* foreign); /* in, own: foreign key struct */
/************************************************************************
+Checks if the database name in two table names is the same. */
+static
+ibool
+dict_tables_have_same_db(
+/*=====================*/
+ /* out: TRUE if same db name */
+ char* name1, /* in: table name in the form dbname '/' tablename */
+ char* name2) /* in: table name in the form dbname '/' tablename */
+{
+ ulint i;
+
+ for (i = 0; i < 100000; i++) {
+ if (name1[i] == '/' && name2[i] == '/') {
+
+ return(TRUE);
+ }
+
+ if (name1[i] != name2[i]) {
+
+ return(FALSE);
+ }
+ }
+
+ ut_a(0);
+
+ return(FALSE);
+}
+
+/************************************************************************
+Return the end of table name where we have removed dbname and '/'. */
+static
+char*
+dict_remove_db_name(
+/*================*/
+ /* out: table name */
+ char* name) /* in: table name in the form dbname '/' tablename */
+{
+ ulint i;
+
+ for (i = 0; i < 100000 ; i++) {
+ if (name[i] == '/') {
+
+ return(name + i + 1);
+ }
+ }
+
+ ut_a(0);
+
+ return(NULL);
+}
+
+/************************************************************************
Reserves the dictionary system mutex for MySQL. */
void
@@ -1926,7 +1981,8 @@ dict_scan_col(
old_ptr = ptr;
- while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`') {
+ while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`'
+ && *ptr != '\0') {
ptr++;
}
@@ -2000,7 +2056,7 @@ dict_scan_table_name(
old_ptr = ptr;
- while (!isspace(*ptr) && *ptr != '(' && *ptr != '`') {
+ while (!isspace(*ptr) && *ptr != '(' && *ptr != '`' && *ptr != '\0') {
if (*ptr == '.') {
dot_ptr = ptr;
}
@@ -2023,17 +2079,28 @@ dict_scan_table_name(
}
#ifdef __WIN__
ut_cpy_in_lower_case(second_table_name + i, old_ptr,
- ptr - old_ptr);
+ ptr - old_ptr);
#else
- ut_memcpy(second_table_name + i, old_ptr, ptr - old_ptr);
+ if (srv_lower_case_table_names) {
+ ut_cpy_in_lower_case(second_table_name + i, old_ptr,
+ ptr - old_ptr);
+ } else {
+ ut_memcpy(second_table_name + i, old_ptr,
+ ptr - old_ptr);
+ }
#endif
second_table_name[i + (ptr - old_ptr)] = '\0';
} else {
#ifdef __WIN__
ut_cpy_in_lower_case(second_table_name, old_ptr,
- ptr - old_ptr);
+ ptr - old_ptr);
#else
- ut_memcpy(second_table_name, old_ptr, ptr - old_ptr);
+ if (srv_lower_case_table_names) {
+ ut_cpy_in_lower_case(second_table_name, old_ptr,
+ ptr - old_ptr);
+ } else {
+ ut_memcpy(second_table_name, old_ptr, ptr - old_ptr);
+ }
#endif
second_table_name[dot_ptr - old_ptr] = '/';
second_table_name[ptr - old_ptr] = '\0';
@@ -2051,6 +2118,44 @@ dict_scan_table_name(
}
/*************************************************************************
+Skips one 'word', like an id. For the lexical definition of 'word', see the
+code below. */
+static
+char*
+dict_skip_word(
+/*===========*/
+ /* out: scanned to */
+ char* ptr, /* in: scanned to */
+ ibool* success)/* out: TRUE if success, FALSE if just spaces left in
+ string */
+{
+ *success = FALSE;
+
+ while (isspace(*ptr)) {
+ ptr++;
+ }
+
+ if (*ptr == '\0') {
+
+ return(ptr);
+ }
+
+ if (*ptr == '`') {
+ ptr++;
+ }
+
+ while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != '`'
+ && *ptr != '\0') {
+
+ ptr++;
+ }
+
+ *success = TRUE;
+
+ return(ptr);
+}
+
+/*************************************************************************
Returns the number of opening brackets '(' subtracted by the number
of closing brackets ')' between string and ptr. */
static
@@ -2119,7 +2224,6 @@ dict_create_foreign_constraints(
if (table == NULL) {
return(DB_ERROR);
}
-
loop:
ptr = dict_scan_to(ptr, (char *) "FOREIGN");
@@ -2148,7 +2252,19 @@ loop:
ptr = dict_accept(ptr, (char *) "(", &success);
if (!success) {
- goto loop;
+ /* MySQL allows also an index id before the '('; we
+ skip it */
+ ptr = dict_skip_word(ptr, &success);
+
+ if (!success) {
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+ ptr = dict_accept(ptr, (char *) "(", &success);
+
+ if (!success) {
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
}
i = 0;
@@ -2223,6 +2339,7 @@ col_loop1:
if (!success) {
dict_foreign_free(foreign);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2236,6 +2353,7 @@ col_loop2:
if (!success) {
dict_foreign_free(foreign);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2263,14 +2381,20 @@ col_loop2:
ptr = dict_accept(ptr, "DELETE", &success);
if (!success) {
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+ ptr = dict_accept(ptr, "RESTRICT", &success);
+ if (success) {
goto try_find_index;
}
ptr = dict_accept(ptr, "CASCADE", &success);
if (success) {
-
foreign->type = DICT_FOREIGN_ON_DELETE_CASCADE;
goto try_find_index;
@@ -2279,32 +2403,47 @@ col_loop2:
ptr = dict_accept(ptr, "SET", &success);
if (!success) {
-
- goto try_find_index;
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
ptr = dict_accept(ptr, "NULL", &success);
- if (success) {
- for (j = 0; j < foreign->n_fields; j++) {
- if ((dict_index_get_nth_type(
+ if (!success) {
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+ for (j = 0; j < foreign->n_fields; j++) {
+ if ((dict_index_get_nth_type(
foreign->foreign_index, j)->prtype)
& DATA_NOT_NULL) {
- /* It is not sensible to define SET NULL
- if the column is not allowed to be NULL! */
+ /* It is not sensible to define SET NULL
+ if the column is not allowed to be NULL! */
- dict_foreign_free(foreign);
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
+ }
- foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;
+ foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;
+
+try_find_index:
+ /* We check that there are no superfluous words like 'ON UPDATE ...'
+ which we do not support yet. */
- goto try_find_index;
+ ptr = dict_accept(ptr, (char *) "ON", &success);
+
+ if (success) {
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
-try_find_index:
/* Try to find an index which contains the columns as the first fields
and in the right order, and the types are the same as in
foreign->foreign_index */
@@ -2351,6 +2490,7 @@ try_find_index:
referenced_table->referenced_list,
foreign);
}
+
goto loop;
}
@@ -2849,6 +2989,14 @@ dict_update_statistics_low(
ulint size;
ulint sum_of_index_sizes = 0;
+ /* If we have set a high innodb_force_recovery level, do not calculate
+ statistics, as a badly corrupted index can cause a crash in it. */
+
+ if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
+
+ return;
+ }
+
/* Find out the sizes of the indexes and how many different values
for the key they approximately have */
@@ -3152,16 +3300,25 @@ dict_print_info_on_foreign_keys_in_create_format(
}
}
- buf2 += sprintf(buf2, ") REFERENCES `%s` (",
+ if (dict_tables_have_same_db(table->name,
+ foreign->referenced_table_name)) {
+ /* Do not print the database name of the referenced
+ table */
+ buf2 += sprintf(buf2, ") REFERENCES `%s` (",
+ dict_remove_db_name(
+ foreign->referenced_table_name));
+ } else {
+ buf2 += sprintf(buf2, ") REFERENCES `%s` (",
foreign->referenced_table_name);
- /* Change the '/' in the table name to '.' */
+ /* Change the '/' in the table name to '.' */
- for (i = ut_strlen(buf); i > 0; i--) {
- if (buf[i] == '/') {
+ for (i = ut_strlen(buf); i > 0; i--) {
+ if (buf[i] == '/') {
- buf[i] = '.';
+ buf[i] = '.';
- break;
+ break;
+ }
}
}