summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <heikki@hundin.mysql.fi>2004-02-02 00:10:45 +0200
committerunknown <heikki@hundin.mysql.fi>2004-02-02 00:10:45 +0200
commit08177508f5db7c003ebbe1fe16e17dd02fff49b0 (patch)
treec00e983defe37f950e64718fcfe3a3ca0daabadc /innobase
parent7eefcb75db0707dbc8044808390f047b60484454 (diff)
downloadmariadb-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.c290
-rw-r--r--innobase/row/row0mysql.c26
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);