summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--innobase/dict/dict0dict.c22
-rw-r--r--innobase/include/dict0dict.h7
-rw-r--r--innobase/include/os0file.h11
-rw-r--r--innobase/include/trx0trx.h19
-rw-r--r--innobase/include/ut0mem.h12
-rw-r--r--innobase/os/os0file.c23
-rw-r--r--innobase/row/row0ins.c40
-rw-r--r--innobase/trx/trx0trx.c27
-rw-r--r--innobase/ut/ut0mem.c25
-rw-r--r--mysql-test/r/innodb.result29
-rw-r--r--mysql-test/t/innodb.test42
-rw-r--r--sql/ha_innodb.cc16
-rw-r--r--sql/ha_innodb.h2
-rw-r--r--sql/handler.cc20
-rw-r--r--sql/share/errmsg.txt4
15 files changed, 274 insertions, 25 deletions
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 5eee57c250b..54df582d39c 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -2189,7 +2189,7 @@ dict_foreign_error_report(
dict_foreign_error_report_low(file, fk->foreign_table_name);
fputs(msg, file);
fputs(" Constraint:\n", file);
- dict_print_info_on_foreign_key_in_create_format(file, NULL, fk);
+ dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE);
if (fk->foreign_index) {
fputs("\nThe index in the foreign key in table is ", file);
ut_print_name(file, NULL, fk->foreign_index->name);
@@ -4330,9 +4330,10 @@ CREATE TABLE. */
void
dict_print_info_on_foreign_key_in_create_format(
/*============================================*/
- FILE* file, /* in: file where to print */
- trx_t* trx, /* in: transaction */
- dict_foreign_t* foreign)/* in: foreign key constraint */
+ FILE* file, /* in: file where to print */
+ trx_t* trx, /* in: transaction */
+ dict_foreign_t* foreign, /* in: foreign key constraint */
+ ibool add_newline) /* in: whether to add a newline */
{
const char* stripped_id;
ulint i;
@@ -4345,7 +4346,16 @@ dict_print_info_on_foreign_key_in_create_format(
stripped_id = foreign->id;
}
- fputs(",\n CONSTRAINT ", file);
+ putc(',', file);
+
+ if (add_newline) {
+ /* SHOW CREATE TABLE wants constraints each printed nicely
+ on its own line, while error messages want no newlines
+ inserted. */
+ fputs("\n ", file);
+ }
+
+ fputs(" CONSTRAINT ", file);
ut_print_name(file, trx, stripped_id);
fputs(" FOREIGN KEY (", file);
@@ -4447,7 +4457,7 @@ dict_print_info_on_foreign_keys(
while (foreign != NULL) {
if (create_table_format) {
dict_print_info_on_foreign_key_in_create_format(
- file, trx, foreign);
+ file, trx, foreign, TRUE);
} else {
ulint i;
fputs("; (", file);
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index a1232acdca7..5215d51cabe 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -375,9 +375,10 @@ CREATE TABLE. */
void
dict_print_info_on_foreign_key_in_create_format(
/*============================================*/
- FILE* file, /* in: file where to print */
- trx_t* trx, /* in: transaction */
- dict_foreign_t* foreign);/* in: foreign key constraint */
+ FILE* file, /* in: file where to print */
+ trx_t* trx, /* in: transaction */
+ dict_foreign_t* foreign, /* in: foreign key constraint */
+ ibool add_newline); /* in: whether to add a newline */
/************************************************************************
Displays the names of the index and the table. */
void
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index adbc4afafd2..224fd59a76b 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -432,6 +432,17 @@ os_file_read(
offset */
ulint n); /* in: number of bytes to read */
/***********************************************************************
+Rewind file to its start, read at most size - 1 bytes from it to str, and
+NUL-terminate str. All errors are silently ignored. This function is
+mostly meant to be used with temporary files. */
+
+void
+os_file_read_string(
+/*================*/
+ FILE* file, /* in: file to read from */
+ char* str, /* in: buffer where to read */
+ ulint size); /* in: size of buffer */
+/***********************************************************************
Requests a synchronous positioned read operation. This function does not do
any error handling. In case of error it returns FALSE. */
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 5dbf003594f..b2081147351 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -56,6 +56,22 @@ void
trx_search_latch_release_if_reserved(
/*=================================*/
trx_t* trx); /* in: transaction */
+/**********************************************************************
+Set detailed error message for the transaction. */
+void
+trx_set_detailed_error(
+/*===================*/
+ trx_t* trx, /* in: transaction struct */
+ char* msg); /* in: detailed error message */
+/*****************************************************************
+Set detailed error message for the transaction from a file. Note that the
+file is rewinded before reading from it. */
+
+void
+trx_set_detailed_error_from_file(
+/*=============================*/
+ trx_t* trx, /* in: transaction struct */
+ FILE* file); /* in: file to read message from */
/********************************************************************
Retrieves the error_info field from a trx. */
@@ -649,6 +665,9 @@ struct trx_struct{
trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
records which are currently processed
by a rollback operation */
+ /*------------------------------*/
+ char detailed_error[256]; /* detailed error message for last
+ error, or empty. */
};
#define TRX_MAX_N_THREADS 32 /* maximum number of concurrent
diff --git a/innobase/include/ut0mem.h b/innobase/include/ut0mem.h
index 74357f6bf13..8f109a64b55 100644
--- a/innobase/include/ut0mem.h
+++ b/innobase/include/ut0mem.h
@@ -119,6 +119,18 @@ int
ut_strcmp(const void* str1, const void* str2);
/**************************************************************************
+Copies up to size - 1 characters from the NUL-terminated string src to
+dst, NUL-terminating the result. Returns strlen(src), so truncation
+occurred if the return value >= size. */
+ulint
+ut_strlcpy(
+/*=======*/
+ /* out: strlen(src) */
+ char* dst, /* in: destination buffer */
+ const char* src, /* in: source buffer */
+ ulint size); /* in: size of destination buffer */
+
+/**************************************************************************
Compute strlen(ut_strcpyq(str, q)). */
UNIV_INLINE
ulint
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 9c87b59f018..20a3303d12d 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -2249,6 +2249,29 @@ error_handling:
}
/***********************************************************************
+Rewind file to its start, read at most size - 1 bytes from it to str, and
+NUL-terminate str. All errors are silently ignored. This function is
+mostly meant to be used with temporary files. */
+
+void
+os_file_read_string(
+/*================*/
+ FILE* file, /* in: file to read from */
+ char* str, /* in: buffer where to read */
+ ulint size) /* in: size of buffer */
+{
+ size_t flen;
+
+ if (size == 0) {
+ return;
+ }
+
+ rewind(file);
+ flen = fread(str, 1, size - 1, file);
+ str[flen] = '\0';
+}
+
+/***********************************************************************
Requests a synchronous write operation. */
ibool
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 75d8117a73e..60d7a640f9a 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -579,6 +579,30 @@ row_ins_cascade_calc_update_vec(
}
/*************************************************************************
+Set detailed error message associated with foreign key errors for
+the given transaction. */
+static
+void
+row_ins_set_detailed(
+/*=================*/
+ trx_t* trx, /* in: transaction */
+ dict_foreign_t* foreign) /* in: foreign key constraint */
+{
+
+ FILE* tf = os_file_create_tmpfile();
+
+ ut_a(tf);
+
+ ut_print_name(tf, trx, foreign->foreign_table_name);
+ dict_print_info_on_foreign_key_in_create_format(tf, trx,
+ foreign, FALSE);
+
+ trx_set_detailed_error_from_file(trx, tf);
+
+ fclose(tf);
+}
+
+/*************************************************************************
Reports a foreign key error associated with an update or a delete of a
parent table index entry. */
static
@@ -598,6 +622,8 @@ row_ins_foreign_report_err(
FILE* ef = dict_foreign_err_file;
trx_t* trx = thr_get_trx(thr);
+ row_ins_set_detailed(trx, foreign);
+
mutex_enter(&dict_foreign_err_mutex);
rewind(ef);
ut_print_timestamp(ef);
@@ -607,7 +633,8 @@ row_ins_foreign_report_err(
fputs("Foreign key constraint fails for table ", ef);
ut_print_name(ef, trx, foreign->foreign_table_name);
fputs(":\n", ef);
- dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign);
+ dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign,
+ TRUE);
putc('\n', ef);
fputs(errstr, ef);
fputs(" in parent table, in index ", ef);
@@ -648,7 +675,9 @@ row_ins_foreign_report_add_err(
child table */
{
FILE* ef = dict_foreign_err_file;
-
+
+ row_ins_set_detailed(trx, foreign);
+
mutex_enter(&dict_foreign_err_mutex);
rewind(ef);
ut_print_timestamp(ef);
@@ -657,7 +686,8 @@ row_ins_foreign_report_add_err(
fputs("Foreign key constraint fails for table ", ef);
ut_print_name(ef, trx, foreign->foreign_table_name);
fputs(":\n", ef);
- dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign);
+ dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign,
+ TRUE);
fputs("\nTrying to add in child table, in index ", ef);
ut_print_name(ef, trx, foreign->foreign_index->name);
if (entry) {
@@ -1223,6 +1253,8 @@ run_again:
if (check_table == NULL || check_table->ibd_file_missing) {
if (check_ref) {
+ row_ins_set_detailed(trx, foreign);
+
FILE* ef = dict_foreign_err_file;
mutex_enter(&dict_foreign_err_mutex);
rewind(ef);
@@ -1233,7 +1265,7 @@ run_again:
ut_print_name(ef, trx, foreign->foreign_table_name);
fputs(":\n", ef);
dict_print_info_on_foreign_key_in_create_format(ef,
- trx, foreign);
+ trx, foreign, TRUE);
fputs("\nTrying to add to index ", ef);
ut_print_name(ef, trx, foreign->foreign_index->name);
fputs(" tuple:\n", ef);
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 078befb81d2..10b95179a73 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -52,6 +52,32 @@ trx_start_if_not_started_noninline(
trx_start_if_not_started(trx);
}
+/*****************************************************************
+Set detailed error message for the transaction. */
+
+void
+trx_set_detailed_error(
+/*===================*/
+ trx_t* trx, /* in: transaction struct */
+ char* msg) /* in: detailed error message */
+{
+ ut_strlcpy(trx->detailed_error, msg, sizeof(trx->detailed_error));
+}
+
+/*****************************************************************
+Set detailed error message for the transaction from a file. Note that the
+file is rewinded before reading from it. */
+
+void
+trx_set_detailed_error_from_file(
+/*=============================*/
+ trx_t* trx, /* in: transaction struct */
+ FILE* file) /* in: file to read message from */
+{
+ os_file_read_string(file, trx->detailed_error,
+ sizeof(trx->detailed_error));
+}
+
/********************************************************************
Retrieves the error_info field from a trx. */
@@ -130,6 +156,7 @@ trx_create(
trx->undo_no_arr = NULL;
trx->error_state = DB_SUCCESS;
+ trx->detailed_error[0] = '\0';
trx->sess = sess;
trx->que_state = TRX_QUE_RUNNING;
diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c
index 3e8fd79a739..c1e3ebbf35c 100644
--- a/innobase/ut/ut0mem.c
+++ b/innobase/ut/ut0mem.c
@@ -343,6 +343,31 @@ ut_free_all_mem(void)
}
/**************************************************************************
+Copies up to size - 1 characters from the NUL-terminated string src to
+dst, NUL-terminating the result. Returns strlen(src), so truncation
+occurred if the return value >= size. */
+
+ulint
+ut_strlcpy(
+/*=======*/
+ /* out: strlen(src) */
+ char* dst, /* in: destination buffer */
+ const char* src, /* in: source buffer */
+ ulint size) /* in: size of destination buffer */
+{
+ ulint src_size = strlen(src);
+
+ if (size != 0) {
+ ulint n = ut_min(src_size, size - 1);
+
+ memcpy(dst, src, n);
+ dst[n] = '\0';
+ }
+
+ return src_size;
+}
+
+/**************************************************************************
Make a quoted copy of a NUL-terminated string. Leading and trailing
quotes will not be included; only embedded quotes will be escaped.
See also ut_strlenq() and ut_memcpyq(). */
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index ffc4ab08ab4..d528e7f43d9 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -1378,9 +1378,9 @@ insert into `t2`values ( 1 ) ;
create table `t3` (`id` int( 11 ) not null default '0',key `id` ( `id` ) ,constraint `t2_id_fk` foreign key ( `id` ) references `t2` (`id` )) engine = innodb;
insert into `t3`values ( 1 ) ;
delete t3,t2,t1 from t1,t2,t3 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
update t1,t2,t3 set t3.id=5, t2.id=6, t1.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
ERROR 42S22: Unknown column 't1.id' in 'where clause'
drop table t3,t2,t1;
@@ -1392,7 +1392,7 @@ foreign key(pid) references t1(id) on delete cascade) engine=innodb;
insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6),
(8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14);
delete from t1 where id=0;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `t1` (`id`) ON DELETE CASCADE)
delete from t1 where id=15;
delete from t1 where id=0;
drop table t1;
@@ -2559,3 +2559,26 @@ FOREIGN KEY (b) REFERENCES test.t1(id)
) ENGINE=InnoDB;
Got one of the listed errors
DROP TABLE t1;
+CREATE TABLE t1
+(
+id INT PRIMARY KEY
+) ENGINE=InnoDB;
+CREATE TABLE t2
+(
+v INT,
+CONSTRAINT c1 FOREIGN KEY (v) REFERENCES t1(id)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES(2);
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`))
+INSERT INTO t1 VALUES(1);
+INSERT INTO t2 VALUES(1);
+DELETE FROM t1 WHERE id = 1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`))
+DROP TABLE t1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+SET FOREIGN_KEY_CHECKS=0;
+DROP TABLE t1;
+SET FOREIGN_KEY_CHECKS=1;
+INSERT INTO t2 VALUES(3);
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`))
+DROP TABLE t2;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 94f33738c8c..d0ebcb9aee8 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -978,9 +978,9 @@ create table `t2` (`id` int( 11 ) not null default '0',unique key `id` ( `id` )
insert into `t2`values ( 1 ) ;
create table `t3` (`id` int( 11 ) not null default '0',key `id` ( `id` ) ,constraint `t2_id_fk` foreign key ( `id` ) references `t2` (`id` )) engine = innodb;
insert into `t3`values ( 1 ) ;
---error 1217
+--error 1451
delete t3,t2,t1 from t1,t2,t3 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
---error 1217
+--error 1451
update t1,t2,t3 set t3.id=5, t2.id=6, t1.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
--error 1054
update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
@@ -996,7 +996,7 @@ create table t1(
foreign key(pid) references t1(id) on delete cascade) engine=innodb;
insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6),
(8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14);
--- error 1217
+-- error 1451
delete from t1 where id=0;
delete from t1 where id=15;
delete from t1 where id=0;
@@ -1482,3 +1482,39 @@ CREATE TEMPORARY TABLE t2
FOREIGN KEY (b) REFERENCES test.t1(id)
) ENGINE=InnoDB;
DROP TABLE t1;
+
+#
+# Test improved foreign key error messages (bug #3443)
+#
+
+CREATE TABLE t1
+(
+ id INT PRIMARY KEY
+) ENGINE=InnoDB;
+
+CREATE TABLE t2
+(
+ v INT,
+ CONSTRAINT c1 FOREIGN KEY (v) REFERENCES t1(id)
+) ENGINE=InnoDB;
+
+--error 1452
+INSERT INTO t2 VALUES(2);
+
+INSERT INTO t1 VALUES(1);
+INSERT INTO t2 VALUES(1);
+
+--error 1451
+DELETE FROM t1 WHERE id = 1;
+
+--error 1217
+DROP TABLE t1;
+
+SET FOREIGN_KEY_CHECKS=0;
+DROP TABLE t1;
+SET FOREIGN_KEY_CHECKS=1;
+
+--error 1452
+INSERT INTO t2 VALUES(3);
+
+DROP TABLE t2;
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 9e10873ad63..d66996f8029 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -6065,6 +6065,8 @@ ha_innobase::start_stmt(
}
}
+ trx->detailed_error[0] = '\0';
+
/* Set the MySQL flag to mark that there is an active transaction */
if (trx->active_trans == 0) {
@@ -6138,6 +6140,8 @@ ha_innobase::external_lock(
if (lock_type != F_UNLCK) {
/* MySQL is setting a new table lock */
+ trx->detailed_error[0] = '\0';
+
/* Set the MySQL flag to mark that there is an active
transaction */
if (trx->active_trans == 0) {
@@ -6941,6 +6945,18 @@ ha_innobase::reset_auto_increment(ulonglong value)
DBUG_RETURN(0);
}
+/* See comment in handler.cc */
+bool
+ha_innobase::get_error_message(int error, String *buf)
+{
+ trx_t* trx = check_trx_exists(current_thd);
+
+ buf->copy(trx->detailed_error, strlen(trx->detailed_error),
+ system_charset_info);
+
+ return FALSE;
+}
+
/***********************************************************************
Compares two 'refs'. A 'ref' is the (internal) primary key value of the row.
If there is no explicitly declared non-null unique key or a primary key, then
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 1c02ac20bb4..d3c7af432a0 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -174,6 +174,8 @@ class ha_innobase: public handler
void init_table_handle_for_HANDLER();
ulonglong get_auto_increment();
int reset_auto_increment(ulonglong value);
+
+ virtual bool get_error_message(int error, String *buf);
uint8 table_cache_type() { return HA_CACHE_TBL_ASKTRANSACT; }
/*
diff --git a/sql/handler.cc b/sql/handler.cc
index 612fd0e0ca5..e0698b37e5f 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -344,8 +344,8 @@ static int ha_init_errors(void)
SETMSG(HA_ERR_READ_ONLY_TRANSACTION, ER(ER_READ_ONLY_TRANSACTION));
SETMSG(HA_ERR_LOCK_DEADLOCK, ER(ER_LOCK_DEADLOCK));
SETMSG(HA_ERR_CANNOT_ADD_FOREIGN, ER(ER_CANNOT_ADD_FOREIGN));
- SETMSG(HA_ERR_NO_REFERENCED_ROW, ER(ER_NO_REFERENCED_ROW));
- SETMSG(HA_ERR_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED));
+ SETMSG(HA_ERR_NO_REFERENCED_ROW, ER(ER_NO_REFERENCED_ROW_2));
+ SETMSG(HA_ERR_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED_2));
SETMSG(HA_ERR_NO_SAVEPOINT, "No savepoint with that name");
SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE, "Non unique key block size");
SETMSG(HA_ERR_NO_SUCH_TABLE, "No such table: '%.64s'");
@@ -1798,11 +1798,19 @@ void handler::print_error(int error, myf errflag)
textno=ER_CANNOT_ADD_FOREIGN;
break;
case HA_ERR_ROW_IS_REFERENCED:
- textno=ER_ROW_IS_REFERENCED;
- break;
+ {
+ String str;
+ get_error_message(error, &str);
+ my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
+ DBUG_VOID_RETURN;
+ }
case HA_ERR_NO_REFERENCED_ROW:
- textno=ER_NO_REFERENCED_ROW;
- break;
+ {
+ String str;
+ get_error_message(error, &str);
+ my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
+ DBUG_VOID_RETURN;
+ }
case HA_ERR_TABLE_DEF_CHANGED:
textno=ER_TABLE_DEF_CHANGED;
break;
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 09589c98dce..c9b717211ce 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5415,3 +5415,7 @@ ER_NO_SUCH_USER
eng "There is not %-.64s@%-.64s registered"
ER_FORBID_SCHEMA_CHANGE
eng "Changing schema from '%-.64s' to '%-.64s' is not allowed."
+ER_ROW_IS_REFERENCED_2 23000
+ eng "Cannot delete or update a parent row: a foreign key constraint fails (%.192s)"
+ER_NO_REFERENCED_ROW_2 23000
+ eng "Cannot add or update a child row: a foreign key constraint fails (%.192s)"