diff options
author | unknown <heikki@hundin.mysql.fi> | 2004-02-02 00:10:45 +0200 |
---|---|---|
committer | unknown <heikki@hundin.mysql.fi> | 2004-02-02 00:10:45 +0200 |
commit | 08177508f5db7c003ebbe1fe16e17dd02fff49b0 (patch) | |
tree | c00e983defe37f950e64718fcfe3a3ca0daabadc /innobase | |
parent | 7eefcb75db0707dbc8044808390f047b60484454 (diff) | |
download | mariadb-git-08177508f5db7c003ebbe1fe16e17dd02fff49b0.tar.gz |
dict0dict.c:
Remove redundant code; parse both the database name and the table name in a FOREIGN KEY constraint with quotes in mind
row0mysql.c, ha_innodb.cc, sql_table.cc:
Return error message Cannot delete or update a parent row... if we try to drop a table which is referenced by a FOREIGN KEY constraint, and the user has not set foreign_key_checks=0
sql/sql_table.cc:
Return error message Cannot delete or update a parent row... if we try to drop a table which is referenced by a FOREIGN KEY constraint, and the user has not set foreign_key_checks=0
sql/ha_innodb.cc:
Return error message Cannot delete or update a parent row... if we try to drop a table which is referenced by a FOREIGN KEY constraint, and the user has not set foreign_key_checks=0
innobase/row/row0mysql.c:
Return error message Cannot delete or update a parent row... if we try to drop a table which is referenced by a FOREIGN KEY constraint, and the user has not set foreign_key_checks=0
innobase/dict/dict0dict.c:
Remove redundant code; parse both the database name and the table name in a FOREIGN KEY constraint with quotes in mind
Diffstat (limited to 'innobase')
-rw-r--r-- | innobase/dict/dict0dict.c | 290 | ||||
-rw-r--r-- | innobase/row/row0mysql.c | 26 |
2 files changed, 151 insertions, 165 deletions
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index b7740321831..d132d082e6a 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -2109,25 +2109,24 @@ dict_accept( } /************************************************************************* -Tries to scan a column name. */ +Scans an id. For the lexical definition of an 'id', see the code below. +Strips backquotes or double quotes from around the id. */ static char* -dict_scan_col( -/*==========*/ +dict_scan_id( +/*=========*/ /* out: scanned to */ - char* ptr, /* in: scanned to */ - ibool* success,/* out: TRUE if success */ - dict_table_t* table, /* in: table in which the column is */ - dict_col_t** column, /* out: pointer to column if success */ - char** column_name,/* out: pointer to column->name if - success */ - ulint* column_name_len)/* out: column name length */ + char* ptr, /* in: scanned to */ + char** start, /* out: start of the id; NULL if no id was + scannable */ + ulint* len, /* out: length of the id */ + ibool accept_also_dot)/* in: TRUE if also a dot can appear in a + non-quoted id; in a quoted id it can appear + always */ { - dict_col_t* col; - char* old_ptr; - ulint i; - - *success = FALSE; + char quote = '\0'; + + *start = NULL; while (isspace(*ptr)) { ptr++; @@ -2139,51 +2138,76 @@ dict_scan_col( } if (*ptr == '`' || *ptr == '"') { - /* The identifier is quoted. Search for the end quote. We - cannot use the general code here as the name may contain - special characters like the space. */ - - char quote = *ptr; - - ptr++; /* Skip the quote */ - - old_ptr = ptr; - - /* The column name should always end with 'quote' but we check - for an end zero just to be safe if this is called outside of - MySQL. */ + quote = *ptr++; + } + + *start = ptr; - while (*ptr && *ptr != quote) { - ptr++; + if (quote) { + while (*ptr != quote && *ptr != '\0') { + ptr++; } - *column_name_len = (ulint)(ptr - old_ptr); + } else { + while (!isspace(*ptr) && *ptr != '(' && *ptr != ')' + && (accept_also_dot || *ptr != '.') + && *ptr != ',' && *ptr != '\0') { - if (*ptr) { /* Skip end quote */ - ptr++; - } else { - return(ptr); /* Syntax error */ + ptr++; } - } else { - old_ptr = ptr; + } + + *len = (ulint) (ptr - *start); - while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' - && *ptr != '\0') { + if (quote) { + if (*ptr == quote) { ptr++; - } - *column_name_len = (ulint)(ptr - old_ptr); + } else { + /* Syntax error */ + *start = NULL; + } } + + return(ptr); +} + +/************************************************************************* +Tries to scan a column name. */ +static +char* +dict_scan_col( +/*==========*/ + /* out: scanned to */ + char* ptr, /* in: scanned to */ + ibool* success,/* out: TRUE if success */ + dict_table_t* table, /* in: table in which the column is */ + dict_col_t** column, /* out: pointer to column if success */ + char** column_name,/* out: pointer to column->name if + success */ + ulint* column_name_len)/* out: column name length */ +{ + dict_col_t* col; + ulint i; + *success = FALSE; + + ptr = dict_scan_id(ptr, column_name, column_name_len, TRUE); + + if (column_name == NULL) { + + return(ptr); /* Syntax error */ + } + if (table == NULL) { *success = TRUE; *column = NULL; - *column_name = old_ptr; } else { for (i = 0; i < dict_table_get_n_cols(table); i++) { col = dict_table_get_nth_col(table, i); if (ut_strlen(col->name) == *column_name_len - && 0 == ut_cmp_in_lower_case(col->name, old_ptr, + && 0 == ut_cmp_in_lower_case(col->name, + *column_name, *column_name_len)) { /* Found */ @@ -2214,163 +2238,99 @@ dict_scan_table_name( the referenced table name; must be at least 2500 bytes */ { - char* dot_ptr = NULL; - char* old_ptr; - char quote = '\0'; + char* database_name = NULL; + ulint database_name_len = 999999999; /* init to a dummy value to + suppress a compiler warning */ + char* table_name = NULL; + ulint table_name_len; + char* scanned_id; + ulint scanned_id_len; ulint i; *success = FALSE; *table = NULL; + + ptr = dict_scan_id(ptr, &scanned_id, &scanned_id_len, FALSE); - while (isspace(*ptr)) { - ptr++; + if (scanned_id == NULL) { + + return(ptr); /* Syntax error */ } - if (*ptr == '\0') { - - return(ptr); - } + if (*ptr == '.') { + /* We scanned the database name; scan also the table name */ - if (*ptr == '`' || *ptr == '"') { - quote = *ptr; ptr++; - } - old_ptr = ptr; + database_name = scanned_id; + database_name_len = scanned_id_len; - if (quote) { - while (*ptr != quote && *ptr != '\0') { - ptr++; - } + ptr = dict_scan_id(ptr, &table_name, &table_name_len, FALSE); - if (*ptr == '\0') { + if (table_name == NULL) { - return(old_ptr); /* Syntax error */ + return(ptr); /* Syntax error */ } } else { - while (!isspace(*ptr) && *ptr != '(' && *ptr != '\0') { + table_name = scanned_id; + table_name_len = scanned_id_len; + } - if (*ptr == '.') { - dot_ptr = ptr; - } - ptr++; + if (database_name == NULL) { + /* Use the database name of the foreign key table */ + + database_name = name; + + i = 0; + while (name[i] != '/') { + i++; } + + database_name_len = i; } - if (ptr - old_ptr > 2000) { + if (table_name_len + database_name_len > 2000) { - return(old_ptr); + return(ptr); /* Too long name */ } - if (dot_ptr == NULL) { - /* Copy the database name from 'name' to the start */ - for (i = 0;; i++) { - second_table_name[i] = name[i]; - if (name[i] == '/') { - i++; - break; - } - } #ifdef __WIN__ - ut_cpy_in_lower_case(second_table_name + i, old_ptr, - ptr - old_ptr); + ut_cpy_in_lower_case(second_table_name, database_name, + database_name_len); #else - 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'; + if (srv_lower_case_table_names) { + ut_cpy_in_lower_case(second_table_name, database_name, + database_name_len); } else { + ut_memcpy(second_table_name, database_name, + database_name_len); + } +#endif + second_table_name[database_name_len] = '/'; + #ifdef __WIN__ - ut_cpy_in_lower_case(second_table_name, old_ptr, - ptr - old_ptr); + ut_cpy_in_lower_case(second_table_name + database_name_len + 1, + table_name, table_name_len); #else - 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'; + if (srv_lower_case_table_names) { + ut_cpy_in_lower_case(second_table_name + database_name_len + 1, + table_name, table_name_len); + } else { + ut_memcpy(second_table_name + database_name_len + 1, + table_name, table_name_len); } +#endif + second_table_name[database_name_len + 1 + table_name_len] = '\0'; *success = TRUE; *table = dict_table_get_low(second_table_name); - if (quote && *ptr == quote) { - ptr++; - } - - return(ptr); -} - -/************************************************************************* -Scans an id. For the lexical definition of an 'id', see the code below. -Strips backquotes from around the id. */ -static -char* -dict_scan_id( -/*=========*/ - /* out: scanned to */ - char* ptr, /* in: scanned to */ - char** start, /* out: start of the id; NULL if no id was - scannable */ - ulint* len) /* out: length of the id */ -{ - char quote = '\0'; - - *start = NULL; - - while (isspace(*ptr)) { - ptr++; - } - - if (*ptr == '\0') { - - return(ptr); - } - - if (*ptr == '`' || *ptr == '"') { - quote = *ptr++; - } - - *start = ptr; - - if (quote) { - while (*ptr != quote && *ptr != '\0') { - ptr++; - } - } else { - while (!isspace(*ptr) && *ptr != '(' && *ptr != ')' - && *ptr != ',' && *ptr != '\0') { - - ptr++; - } - } - - *len = (ulint) (ptr - *start); - - if (quote) { - if (*ptr == quote) { - ptr++; - } else { - /* Syntax error */ - *start = NULL; - } - } - return(ptr); } /************************************************************************* -Skips one id. */ +Skips one id. The id is allowed to contain also '.'. */ static char* dict_skip_word( @@ -2385,7 +2345,7 @@ dict_skip_word( *success = FALSE; - ptr = dict_scan_id(ptr, &start, &len); + ptr = dict_scan_id(ptr, &start, &len, TRUE); if (start) { *success = TRUE; @@ -3083,7 +3043,7 @@ loop: goto syntax_error; } - ptr = dict_scan_id(ptr, &start, &len); + ptr = dict_scan_id(ptr, &start, &len, TRUE); if (start == NULL) { diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 468404268f4..257756ff8aa 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1804,6 +1804,7 @@ row_drop_table_for_mysql( char* name, /* in: table name */ trx_t* trx) /* in: transaction handle */ { + dict_foreign_t* foreign; dict_table_t* table; que_thr_t* thr; que_t* graph; @@ -1996,6 +1997,31 @@ row_drop_table_for_mysql( goto funct_exit; } + foreign = UT_LIST_GET_FIRST(table->referenced_list); + + if (foreign && trx->check_foreigns) { + char* buf = dict_foreign_err_buf; + + /* We only allow dropping a referenced table if + FOREIGN_KEY_CHECKS is set to 0 */ + + err = DB_CANNOT_DROP_CONSTRAINT; + + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + + sprintf(buf + strlen(buf), + " Cannot drop table %.500s\n", name); + sprintf(buf + strlen(buf), +"because it is referenced by %.500s\n", foreign->foreign_table_name); + + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + + mutex_exit(&dict_foreign_err_mutex); + + goto funct_exit; + } + if (table->n_mysql_handles_opened > 0) { ut_print_timestamp(stderr); |