summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <sergefp@mysql.com>2005-09-25 01:36:26 +0400
committerunknown <sergefp@mysql.com>2005-09-25 01:36:26 +0400
commitbd8b5dc8457ebed6489eeaa07c0beafd068d0dad (patch)
tree6d7a437fe700037a7dfd6bfd28cafeb2efe4e266 /innobase
parent8423c278b16177fcd6440ac9146508ded6dc3631 (diff)
parentf437ec9aee07473fbd0d1674c206fe42e482b41f (diff)
downloadmariadb-git-bd8b5dc8457ebed6489eeaa07c0beafd068d0dad.tar.gz
Merge spetrunia@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/psergey/mysql-5.0-bug13317
Diffstat (limited to 'innobase')
-rw-r--r--innobase/data/data0data.c10
-rw-r--r--innobase/dict/dict0dict.c24
-rw-r--r--innobase/include/data0type.ic2
-rw-r--r--innobase/include/dict0dict.h7
-rw-r--r--innobase/include/dict0mem.h14
-rw-r--r--innobase/include/os0file.h11
-rw-r--r--innobase/include/row0mysql.h10
-rw-r--r--innobase/include/trx0trx.h21
-rw-r--r--innobase/include/ut0mem.h12
-rw-r--r--innobase/os/os0file.c23
-rw-r--r--innobase/rem/rem0rec.c2
-rw-r--r--innobase/row/row0ins.c41
-rw-r--r--innobase/row/row0mysql.c21
-rw-r--r--innobase/trx/trx0trx.c27
-rw-r--r--innobase/ut/ut0mem.c25
15 files changed, 215 insertions, 35 deletions
diff --git a/innobase/data/data0data.c b/innobase/data/data0data.c
index 194213a04e1..19304a7a8e1 100644
--- a/innobase/data/data0data.c
+++ b/innobase/data/data0data.c
@@ -561,12 +561,12 @@ dtuple_convert_big_rec(
}
/* We do not store externally fields which are smaller than
- DICT_MAX_COL_PREFIX_LEN */
+ DICT_MAX_INDEX_COL_LEN */
- ut_a(DICT_MAX_COL_PREFIX_LEN > REC_1BYTE_OFFS_LIMIT);
+ ut_a(DICT_MAX_INDEX_COL_LEN > REC_1BYTE_OFFS_LIMIT);
if (longest < BTR_EXTERN_FIELD_REF_SIZE + 10
- + DICT_MAX_COL_PREFIX_LEN) {
+ + DICT_MAX_INDEX_COL_LEN) {
/* Cannot shorten more */
mem_heap_free(heap);
@@ -588,10 +588,10 @@ dtuple_convert_big_rec(
dfield = dtuple_get_nth_field(entry, longest_i);
vector->fields[n_fields].field_no = longest_i;
- ut_a(dfield->len > DICT_MAX_COL_PREFIX_LEN);
+ ut_a(dfield->len > DICT_MAX_INDEX_COL_LEN);
vector->fields[n_fields].len = dfield->len
- - DICT_MAX_COL_PREFIX_LEN;
+ - DICT_MAX_INDEX_COL_LEN;
vector->fields[n_fields].data = mem_heap_alloc(heap,
vector->fields[n_fields].len);
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 5eee57c250b..fb95ffbd80c 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -1625,7 +1625,7 @@ dict_index_add_col(
variable-length fields, so that the extern flag can be embedded in
the length word. */
- if (field->fixed_len > DICT_MAX_COL_PREFIX_LEN) {
+ if (field->fixed_len > DICT_MAX_INDEX_COL_LEN) {
field->fixed_len = 0;
}
@@ -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/data0type.ic b/innobase/include/data0type.ic
index 06d45dd5501..d4a7b3c64b8 100644
--- a/innobase/include/data0type.ic
+++ b/innobase/include/data0type.ic
@@ -420,7 +420,7 @@ dtype_get_fixed_size(
}
/***************************************************************************
-Returns the size of a fixed size data type, 0 if not a fixed size type. */
+Returns the minimum size of a data type. */
UNIV_INLINE
ulint
dtype_get_min_size(
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/dict0mem.h b/innobase/include/dict0mem.h
index ff6c4ec9b28..7eec86d0bcb 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -152,12 +152,12 @@ struct dict_col_struct{
in some of the functions below */
};
-/* DICT_MAX_COL_PREFIX_LEN is measured in bytes. Starting from 4.1.6, we
-set max col prefix len to < 3 * 256, so that one can create a column prefix
-index on 255 characters of a TEXT field also in the UTF-8 charset. In that
-charset, a character may take at most 3 bytes. */
+/* DICT_MAX_INDEX_COL_LEN is measured in bytes and is the max index column
+length + 1. Starting from 4.1.6, we set it to < 3 * 256, so that one can
+create a column prefix index on 255 characters of a TEXT field also in the
+UTF-8 charset. In that charset, a character may take at most 3 bytes. */
-#define DICT_MAX_COL_PREFIX_LEN 768
+#define DICT_MAX_INDEX_COL_LEN 768
/* Data structure for a field in an index */
struct dict_field_struct{
@@ -169,12 +169,12 @@ struct dict_field_struct{
prefix in bytes in a MySQL index of
type, e.g., INDEX (textcol(25));
must be smaller than
- DICT_MAX_COL_PREFIX_LEN; NOTE that
+ DICT_MAX_INDEX_COL_LEN; NOTE that
in the UTF-8 charset, MySQL sets this
to 3 * the prefix len in UTF-8 chars */
ulint fixed_len; /* 0 or the fixed length of the
column if smaller than
- DICT_MAX_COL_PREFIX_LEN */
+ DICT_MAX_INDEX_COL_LEN */
ulint fixed_offs; /* offset to the field, or
ULINT_UNDEFINED if it is not fixed
within the record (due to preceding
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/row0mysql.h b/innobase/include/row0mysql.h
index a61705b90be..b5da4634d98 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -335,8 +335,14 @@ int
row_create_index_for_mysql(
/*=======================*/
/* out: error number or DB_SUCCESS */
- dict_index_t* index, /* in: index defintion */
- trx_t* trx); /* in: transaction handle */
+ dict_index_t* index, /* in: index definition */
+ trx_t* trx, /* in: transaction handle */
+ const ulint* field_lengths); /* in: if not NULL, must contain
+ dict_index_get_n_fields(index)
+ actual field lengths for the
+ index columns, which are
+ then checked for not being too
+ large. */
/*************************************************************************
Scans a table create SQL string and adds to the data dictionary
the foreign key constraints declared in the string. This function
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 5dbf003594f..964491f747b 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. */
@@ -205,7 +221,7 @@ trx_recover_for_mysql(
XID* xid_list, /* in/out: prepared transactions */
ulint len); /* in: number of slots in xid_list */
/***********************************************************************
-This function is used to commit one X/Open XA distributed transaction
+This function is used to find one X/Open XA distributed transaction
which is in the prepared state */
trx_t *
trx_get_trx_by_xid(
@@ -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/rem/rem0rec.c b/innobase/rem/rem0rec.c
index fbc33aea669..9480c978755 100644
--- a/innobase/rem/rem0rec.c
+++ b/innobase/rem/rem0rec.c
@@ -621,7 +621,7 @@ rec_set_nth_field_extern_bit_new(
if (field->fixed_len) {
/* fixed-length fields cannot be external
(Fixed-length fields longer than
- DICT_MAX_COL_PREFIX_LEN will be treated as
+ DICT_MAX_INDEX_COL_LEN will be treated as
variable-length ones in dict_index_add_col().) */
ut_ad(i != ith);
continue;
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 75d8117a73e..db871a53c42 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) {
@@ -1224,6 +1254,9 @@ run_again:
if (check_table == NULL || check_table->ibd_file_missing) {
if (check_ref) {
FILE* ef = dict_foreign_err_file;
+
+ row_ins_set_detailed(trx, foreign);
+
mutex_enter(&dict_foreign_err_mutex);
rewind(ef);
ut_print_timestamp(ef);
@@ -1233,7 +1266,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/row/row0mysql.c b/innobase/row/row0mysql.c
index 26aae117d1d..82f7daf2ed8 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -1973,13 +1973,20 @@ row_create_index_for_mysql(
/*=======================*/
/* out: error number or DB_SUCCESS */
dict_index_t* index, /* in: index definition */
- trx_t* trx) /* in: transaction handle */
+ trx_t* trx, /* in: transaction handle */
+ const ulint* field_lengths) /* in: if not NULL, must contain
+ dict_index_get_n_fields(index)
+ actual field lengths for the
+ index columns, which are
+ then checked for not being too
+ large. */
{
ind_node_t* node;
mem_heap_t* heap;
que_thr_t* thr;
ulint err;
ulint i, j;
+ ulint len;
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
@@ -2018,10 +2025,16 @@ row_create_index_for_mysql(
}
}
- /* Check also that prefix_len < DICT_MAX_COL_PREFIX_LEN */
+ /* Check also that prefix_len and actual length
+ < DICT_MAX_INDEX_COL_LEN */
+
+ len = dict_index_get_nth_field(index, i)->prefix_len;
- if (dict_index_get_nth_field(index, i)->prefix_len
- >= DICT_MAX_COL_PREFIX_LEN) {
+ if (field_lengths) {
+ len = ut_max(len, field_lengths[i]);
+ }
+
+ if (len >= DICT_MAX_INDEX_COL_LEN) {
err = DB_TOO_BIG_RECORD;
goto error_handling;
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(). */