Commit d61708d1 authored by osku@127.(none)'s avatar osku@127.(none)

Fix bug #3443, better foreign key error messsages.

parent f5c00b0d
...@@ -2189,7 +2189,7 @@ dict_foreign_error_report( ...@@ -2189,7 +2189,7 @@ dict_foreign_error_report(
dict_foreign_error_report_low(file, fk->foreign_table_name); dict_foreign_error_report_low(file, fk->foreign_table_name);
fputs(msg, file); fputs(msg, file);
fputs(" Constraint:\n", 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) { if (fk->foreign_index) {
fputs("\nThe index in the foreign key in table is ", file); fputs("\nThe index in the foreign key in table is ", file);
ut_print_name(file, NULL, fk->foreign_index->name); ut_print_name(file, NULL, fk->foreign_index->name);
...@@ -4332,7 +4332,8 @@ dict_print_info_on_foreign_key_in_create_format( ...@@ -4332,7 +4332,8 @@ dict_print_info_on_foreign_key_in_create_format(
/*============================================*/ /*============================================*/
FILE* file, /* in: file where to print */ FILE* file, /* in: file where to print */
trx_t* trx, /* in: transaction */ trx_t* trx, /* in: transaction */
dict_foreign_t* foreign)/* in: foreign key constraint */ dict_foreign_t* foreign, /* in: foreign key constraint */
ibool add_newline) /* in: whether to add a newline */
{ {
const char* stripped_id; const char* stripped_id;
ulint i; ulint i;
...@@ -4345,7 +4346,16 @@ dict_print_info_on_foreign_key_in_create_format( ...@@ -4345,7 +4346,16 @@ dict_print_info_on_foreign_key_in_create_format(
stripped_id = foreign->id; 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); ut_print_name(file, trx, stripped_id);
fputs(" FOREIGN KEY (", file); fputs(" FOREIGN KEY (", file);
...@@ -4447,7 +4457,7 @@ dict_print_info_on_foreign_keys( ...@@ -4447,7 +4457,7 @@ dict_print_info_on_foreign_keys(
while (foreign != NULL) { while (foreign != NULL) {
if (create_table_format) { if (create_table_format) {
dict_print_info_on_foreign_key_in_create_format( dict_print_info_on_foreign_key_in_create_format(
file, trx, foreign); file, trx, foreign, TRUE);
} else { } else {
ulint i; ulint i;
fputs("; (", file); fputs("; (", file);
......
...@@ -377,7 +377,8 @@ dict_print_info_on_foreign_key_in_create_format( ...@@ -377,7 +377,8 @@ dict_print_info_on_foreign_key_in_create_format(
/*============================================*/ /*============================================*/
FILE* file, /* in: file where to print */ FILE* file, /* in: file where to print */
trx_t* trx, /* in: transaction */ trx_t* trx, /* in: transaction */
dict_foreign_t* foreign);/* in: foreign key constraint */ 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. */ Displays the names of the index and the table. */
void void
......
...@@ -432,6 +432,17 @@ os_file_read( ...@@ -432,6 +432,17 @@ os_file_read(
offset */ offset */
ulint n); /* in: number of bytes to read */ 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 Requests a synchronous positioned read operation. This function does not do
any error handling. In case of error it returns FALSE. */ any error handling. In case of error it returns FALSE. */
......
...@@ -56,6 +56,22 @@ void ...@@ -56,6 +56,22 @@ void
trx_search_latch_release_if_reserved( trx_search_latch_release_if_reserved(
/*=================================*/ /*=================================*/
trx_t* trx); /* in: transaction */ 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. */ Retrieves the error_info field from a trx. */
...@@ -649,6 +665,9 @@ struct trx_struct{ ...@@ -649,6 +665,9 @@ struct trx_struct{
trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
records which are currently processed records which are currently processed
by a rollback operation */ 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 #define TRX_MAX_N_THREADS 32 /* maximum number of concurrent
......
...@@ -118,6 +118,18 @@ UNIV_INLINE ...@@ -118,6 +118,18 @@ UNIV_INLINE
int int
ut_strcmp(const void* str1, const void* str2); 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)). */ Compute strlen(ut_strcpyq(str, q)). */
UNIV_INLINE UNIV_INLINE
......
...@@ -2248,6 +2248,29 @@ os_file_read_no_error_handling( ...@@ -2248,6 +2248,29 @@ os_file_read_no_error_handling(
return(FALSE); return(FALSE);
} }
/***********************************************************************
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. */ Requests a synchronous write operation. */
......
...@@ -578,6 +578,30 @@ row_ins_cascade_calc_update_vec( ...@@ -578,6 +578,30 @@ row_ins_cascade_calc_update_vec(
return(n_fields_updated); return(n_fields_updated);
} }
/*************************************************************************
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 Reports a foreign key error associated with an update or a delete of a
parent table index entry. */ parent table index entry. */
...@@ -598,6 +622,8 @@ row_ins_foreign_report_err( ...@@ -598,6 +622,8 @@ row_ins_foreign_report_err(
FILE* ef = dict_foreign_err_file; FILE* ef = dict_foreign_err_file;
trx_t* trx = thr_get_trx(thr); trx_t* trx = thr_get_trx(thr);
row_ins_set_detailed(trx, foreign);
mutex_enter(&dict_foreign_err_mutex); mutex_enter(&dict_foreign_err_mutex);
rewind(ef); rewind(ef);
ut_print_timestamp(ef); ut_print_timestamp(ef);
...@@ -607,7 +633,8 @@ row_ins_foreign_report_err( ...@@ -607,7 +633,8 @@ row_ins_foreign_report_err(
fputs("Foreign key constraint fails for table ", ef); fputs("Foreign key constraint fails for table ", ef);
ut_print_name(ef, trx, foreign->foreign_table_name); ut_print_name(ef, trx, foreign->foreign_table_name);
fputs(":\n", ef); 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); putc('\n', ef);
fputs(errstr, ef); fputs(errstr, ef);
fputs(" in parent table, in index ", ef); fputs(" in parent table, in index ", ef);
...@@ -649,6 +676,8 @@ row_ins_foreign_report_add_err( ...@@ -649,6 +676,8 @@ row_ins_foreign_report_add_err(
{ {
FILE* ef = dict_foreign_err_file; FILE* ef = dict_foreign_err_file;
row_ins_set_detailed(trx, foreign);
mutex_enter(&dict_foreign_err_mutex); mutex_enter(&dict_foreign_err_mutex);
rewind(ef); rewind(ef);
ut_print_timestamp(ef); ut_print_timestamp(ef);
...@@ -657,7 +686,8 @@ row_ins_foreign_report_add_err( ...@@ -657,7 +686,8 @@ row_ins_foreign_report_add_err(
fputs("Foreign key constraint fails for table ", ef); fputs("Foreign key constraint fails for table ", ef);
ut_print_name(ef, trx, foreign->foreign_table_name); ut_print_name(ef, trx, foreign->foreign_table_name);
fputs(":\n", ef); 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); fputs("\nTrying to add in child table, in index ", ef);
ut_print_name(ef, trx, foreign->foreign_index->name); ut_print_name(ef, trx, foreign->foreign_index->name);
if (entry) { if (entry) {
...@@ -1223,6 +1253,8 @@ row_ins_check_foreign_constraint( ...@@ -1223,6 +1253,8 @@ row_ins_check_foreign_constraint(
if (check_table == NULL || check_table->ibd_file_missing) { if (check_table == NULL || check_table->ibd_file_missing) {
if (check_ref) { if (check_ref) {
row_ins_set_detailed(trx, foreign);
FILE* ef = dict_foreign_err_file; FILE* ef = dict_foreign_err_file;
mutex_enter(&dict_foreign_err_mutex); mutex_enter(&dict_foreign_err_mutex);
rewind(ef); rewind(ef);
...@@ -1233,7 +1265,7 @@ row_ins_check_foreign_constraint( ...@@ -1233,7 +1265,7 @@ row_ins_check_foreign_constraint(
ut_print_name(ef, trx, foreign->foreign_table_name); ut_print_name(ef, trx, foreign->foreign_table_name);
fputs(":\n", ef); fputs(":\n", ef);
dict_print_info_on_foreign_key_in_create_format(ef, dict_print_info_on_foreign_key_in_create_format(ef,
trx, foreign); trx, foreign, TRUE);
fputs("\nTrying to add to index ", ef); fputs("\nTrying to add to index ", ef);
ut_print_name(ef, trx, foreign->foreign_index->name); ut_print_name(ef, trx, foreign->foreign_index->name);
fputs(" tuple:\n", ef); fputs(" tuple:\n", ef);
......
...@@ -52,6 +52,32 @@ trx_start_if_not_started_noninline( ...@@ -52,6 +52,32 @@ trx_start_if_not_started_noninline(
trx_start_if_not_started(trx); 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. */ Retrieves the error_info field from a trx. */
...@@ -130,6 +156,7 @@ trx_create( ...@@ -130,6 +156,7 @@ trx_create(
trx->undo_no_arr = NULL; trx->undo_no_arr = NULL;
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
trx->detailed_error[0] = '\0';
trx->sess = sess; trx->sess = sess;
trx->que_state = TRX_QUE_RUNNING; trx->que_state = TRX_QUE_RUNNING;
......
...@@ -342,6 +342,31 @@ ut_free_all_mem(void) ...@@ -342,6 +342,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 Make a quoted copy of a NUL-terminated string. Leading and trailing
quotes will not be included; only embedded quotes will be escaped. quotes will not be included; only embedded quotes will be escaped.
......
...@@ -1378,9 +1378,9 @@ insert into `t2`values ( 1 ) ; ...@@ -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; 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 ) ; 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; 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; 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; 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' ERROR 42S22: Unknown column 't1.id' in 'where clause'
drop table t3,t2,t1; drop table t3,t2,t1;
...@@ -1392,7 +1392,7 @@ foreign key(pid) references t1(id) on delete cascade) engine=innodb; ...@@ -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), 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); (8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14);
delete from t1 where id=0; 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=15;
delete from t1 where id=0; delete from t1 where id=0;
drop table t1; drop table t1;
...@@ -2559,3 +2559,26 @@ FOREIGN KEY (b) REFERENCES test.t1(id) ...@@ -2559,3 +2559,26 @@ FOREIGN KEY (b) REFERENCES test.t1(id)
) ENGINE=InnoDB; ) ENGINE=InnoDB;
Got one of the listed errors Got one of the listed errors
DROP TABLE t1; 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;
...@@ -978,9 +978,9 @@ create table `t2` (`id` int( 11 ) not null default '0',unique key `id` ( `id` ) ...@@ -978,9 +978,9 @@ create table `t2` (`id` int( 11 ) not null default '0',unique key `id` ( `id` )
insert into `t2`values ( 1 ) ; 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; 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 ) ; 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; 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; 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 --error 1054
update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; 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( ...@@ -996,7 +996,7 @@ create table t1(
foreign key(pid) references t1(id) on delete cascade) engine=innodb; 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), 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); (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=0;
delete from t1 where id=15; delete from t1 where id=15;
delete from t1 where id=0; delete from t1 where id=0;
...@@ -1482,3 +1482,39 @@ CREATE TEMPORARY TABLE t2 ...@@ -1482,3 +1482,39 @@ CREATE TEMPORARY TABLE t2
FOREIGN KEY (b) REFERENCES test.t1(id) FOREIGN KEY (b) REFERENCES test.t1(id)
) ENGINE=InnoDB; ) ENGINE=InnoDB;
DROP TABLE t1; 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;
...@@ -6065,6 +6065,8 @@ ha_innobase::start_stmt( ...@@ -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 */ /* Set the MySQL flag to mark that there is an active transaction */
if (trx->active_trans == 0) { if (trx->active_trans == 0) {
...@@ -6138,6 +6140,8 @@ ha_innobase::external_lock( ...@@ -6138,6 +6140,8 @@ ha_innobase::external_lock(
if (lock_type != F_UNLCK) { if (lock_type != F_UNLCK) {
/* MySQL is setting a new table lock */ /* MySQL is setting a new table lock */
trx->detailed_error[0] = '\0';
/* Set the MySQL flag to mark that there is an active /* Set the MySQL flag to mark that there is an active
transaction */ transaction */
if (trx->active_trans == 0) { if (trx->active_trans == 0) {
...@@ -6941,6 +6945,18 @@ ha_innobase::reset_auto_increment(ulonglong value) ...@@ -6941,6 +6945,18 @@ ha_innobase::reset_auto_increment(ulonglong value)
DBUG_RETURN(0); 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. 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 If there is no explicitly declared non-null unique key or a primary key, then
......
...@@ -175,6 +175,8 @@ class ha_innobase: public handler ...@@ -175,6 +175,8 @@ class ha_innobase: public handler
ulonglong get_auto_increment(); ulonglong get_auto_increment();
int reset_auto_increment(ulonglong value); int reset_auto_increment(ulonglong value);
virtual bool get_error_message(int error, String *buf);
uint8 table_cache_type() { return HA_CACHE_TBL_ASKTRANSACT; } uint8 table_cache_type() { return HA_CACHE_TBL_ASKTRANSACT; }
/* /*
ask handler about permission to cache table during query registration ask handler about permission to cache table during query registration
......
...@@ -344,8 +344,8 @@ static int ha_init_errors(void) ...@@ -344,8 +344,8 @@ static int ha_init_errors(void)
SETMSG(HA_ERR_READ_ONLY_TRANSACTION, ER(ER_READ_ONLY_TRANSACTION)); SETMSG(HA_ERR_READ_ONLY_TRANSACTION, ER(ER_READ_ONLY_TRANSACTION));
SETMSG(HA_ERR_LOCK_DEADLOCK, ER(ER_LOCK_DEADLOCK)); SETMSG(HA_ERR_LOCK_DEADLOCK, ER(ER_LOCK_DEADLOCK));
SETMSG(HA_ERR_CANNOT_ADD_FOREIGN, ER(ER_CANNOT_ADD_FOREIGN)); 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_NO_REFERENCED_ROW, ER(ER_NO_REFERENCED_ROW_2));
SETMSG(HA_ERR_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED)); 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_NO_SAVEPOINT, "No savepoint with that name");
SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE, "Non unique key block size"); SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE, "Non unique key block size");
SETMSG(HA_ERR_NO_SUCH_TABLE, "No such table: '%.64s'"); SETMSG(HA_ERR_NO_SUCH_TABLE, "No such table: '%.64s'");
...@@ -1798,11 +1798,19 @@ void handler::print_error(int error, myf errflag) ...@@ -1798,11 +1798,19 @@ void handler::print_error(int error, myf errflag)
textno=ER_CANNOT_ADD_FOREIGN; textno=ER_CANNOT_ADD_FOREIGN;
break; break;
case HA_ERR_ROW_IS_REFERENCED: 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: 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: case HA_ERR_TABLE_DEF_CHANGED:
textno=ER_TABLE_DEF_CHANGED; textno=ER_TABLE_DEF_CHANGED;
break; break;
......
...@@ -5415,3 +5415,7 @@ ER_NO_SUCH_USER ...@@ -5415,3 +5415,7 @@ ER_NO_SUCH_USER
eng "There is not %-.64s@%-.64s registered" eng "There is not %-.64s@%-.64s registered"
ER_FORBID_SCHEMA_CHANGE ER_FORBID_SCHEMA_CHANGE
eng "Changing schema from '%-.64s' to '%-.64s' is not allowed." 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)"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment