summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <monty@hundin.mysql.fi>2002-05-16 18:20:49 +0300
committerunknown <monty@hundin.mysql.fi>2002-05-16 18:20:49 +0300
commit4d094257dbb785d792785e610ab3cdf41eae9b8c (patch)
tree12de711f3f9d8ad9eee9d28cf71e5487f17315d3 /innobase
parent2618c6963c5bf1349c47ce3af6e55213ea9773f4 (diff)
parent74d29a07712a0caf57fca62dacfeb14b110beca4 (diff)
downloadmariadb-git-4d094257dbb785d792785e610ab3cdf41eae9b8c.tar.gz
merge with 3.23.51
BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union BitKeeper/deleted/.del-mysql_fix_extensions.sh: Delete: scripts/mysql_fix_extensions.sh Build-tools/Do-rpm: Auto merged Makefile.am: Auto merged client/mysqldump.c: Auto merged client/mysqltest.c: Auto merged extra/resolve_stack_dump.c: Auto merged include/my_pthread.h: Auto merged include/my_sys.h: Auto merged include/mysqld_error.h: Auto merged innobase/row/row0ins.c: Auto merged innobase/row/row0mysql.c: Auto merged innobase/row/row0sel.c: Auto merged isam/pack_isam.c: Auto merged libmysql/libmysql.c: Auto merged mysql-test/r/func_if.result: Auto merged mysql-test/t/join.test: Auto merged mysys/array.c: Auto merged mysys/charset.c: Auto merged mysys/default.c: Auto merged mysys/hash.c: Auto merged mysys/my_thr_init.c: Auto merged mysys/raid.cc: Auto merged mysql-test/t/type_decimal.test: Auto merged sql/hostname.cc: Auto merged sql/item.h: Auto merged sql/item_cmpfunc.h: Auto merged sql/item_timefunc.h: Auto merged sql/log.cc: Auto merged sql/mini_client.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_select.cc: Auto merged strings/Makefile.am: Auto merged
Diffstat (limited to 'innobase')
-rw-r--r--innobase/row/row0ins.c12
-rw-r--r--innobase/row/row0mysql.c42
-rw-r--r--innobase/row/row0sel.c41
3 files changed, 81 insertions, 14 deletions
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 14e69024a8a..ed4df08fcf3 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -456,7 +456,8 @@ row_ins_foreign_delete_or_set_null(
}
if (!page_rec_is_user_rec(clust_rec)) {
- fprintf(stderr, "InnoDB: error in cascade of a foreign key op\n"
+ fprintf(stderr,
+ "InnoDB: error in cascade of a foreign key op\n"
"InnoDB: index %s table %s\n", index->name,
index->table->name);
@@ -490,9 +491,10 @@ row_ins_foreign_delete_or_set_null(
}
if (rec_get_deleted_flag(clust_rec)) {
- /* This should never happen since we already have an S-lock
- on non-delete-marked clust_rec or secondary index record! */
-
+ /* This can happen if there is a circular reference of
+ rows such that cascading delete comes to delete a row
+ already in the process of being delete marked */
+/*
fprintf(stderr,
"InnoDB: error 2 in cascade of a foreign key op\n"
"InnoDB: index %s table %s\n", index->name,
@@ -509,6 +511,8 @@ row_ins_foreign_delete_or_set_null(
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
ut_a(0);
+*/
+ err = DB_SUCCESS;
goto nonstandard_exit_func;
}
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 841d03acc48..d6c8d7ab412 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -28,6 +28,9 @@ Created 9/17/2000 Heikki Tuuri
#include "rem0cmp.h"
#include "log0log.h"
+/* A dummy variable used to fool the compiler */
+ibool row_mysql_identically_false = FALSE;
+
/* List of tables we should drop in background. ALTER TABLE in MySQL requires
that the table handler can drop the table in background when there are no
queries to it any more. Protected by the kernel mutex. */
@@ -63,15 +66,48 @@ row_mysql_store_blob_ref(
byte* dest, /* in: where to store */
ulint col_len, /* in: dest buffer size: determines into
how many bytes the BLOB length is stored,
- this may vary from 1 to 4 bytes */
- byte* data, /* in: BLOB data */
- ulint len) /* in: BLOB length */
+ the space for the length may vary from 1
+ to 4 bytes */
+ byte* data, /* in: BLOB data; if the value to store
+ is SQL NULL this should be NULL pointer */
+ ulint len) /* in: BLOB length; if the value to store
+ is SQL NULL this should be 0; remember
+ also to set the NULL bit in the MySQL record
+ header! */
{
+ ulint sum = 0;
+ ulint i;
+
+ /* MySQL might assume the field is set to zero except the length and
+ the pointer fields */
+
+ memset(dest, '\0', col_len);
+
/* In dest there are 1 - 4 bytes reserved for the BLOB length,
and after that 8 bytes reserved for the pointer to the data.
In 32-bit architectures we only use the first 4 bytes of the pointer
slot. */
+ ut_a(col_len - 8 > 1 || len < 256);
+ ut_a(col_len - 8 > 2 || len < 256 * 256);
+ ut_a(col_len - 8 > 3 || len < 256 * 256 * 256);
+
+ /* We try to track an elusive bug which probably was fixed
+ May 9, 2002, but better be sure: we probe the data buffer
+ to make sure it is in valid allocated memory */
+
+ for (i = 0; i < len; i++) {
+
+ sum += (ulint)(data + i);
+ }
+
+ /* The variable below is identically false, we just fool the
+ compiler to not optimize away our loop */
+ if (row_mysql_identically_false) {
+
+ printf("Sum %lu\n", sum);
+ }
+
mach_write_to_n_little_endian(dest, col_len - 8, len);
ut_memcpy(dest + col_len - 8, (byte*)&data, sizeof(byte*));
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 8a37e787ba0..f3dced15fdf 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2071,13 +2071,11 @@ row_sel_store_mysql_rec(
data = rec_get_nth_field(rec, templ->rec_field_no, &len);
if (rec_get_nth_field_extern_bit(rec, templ->rec_field_no)) {
+
/* Copy an externally stored field to the temporary
heap */
- if (prebuilt->trx->has_search_latch) {
- rw_lock_s_unlock(&btr_search_latch);
- prebuilt->trx->has_search_latch = FALSE;
- }
+ ut_a(!prebuilt->trx->has_search_latch);
extern_field_heap = mem_heap_create(UNIV_PAGE_SIZE);
@@ -2091,6 +2089,8 @@ row_sel_store_mysql_rec(
if (len != UNIV_SQL_NULL) {
if (templ->type == DATA_BLOB) {
+ ut_a(prebuilt->templ_contains_blob);
+
/* Copy the BLOB data to the BLOB
heap of prebuilt */
@@ -2116,6 +2116,20 @@ row_sel_store_mysql_rec(
extern_field_heap = NULL;
}
} else {
+ /* MySQL sometimes seems to copy the 'data'
+ pointed to by a BLOB field even if the field
+ has been marked to contain the SQL NULL value.
+ This caused seg faults reported by two users.
+ Set the BLOB length to 0 and the data pointer
+ to NULL to avoid a seg fault. */
+
+ if (templ->type == DATA_BLOB) {
+ row_sel_field_store_in_mysql_format(
+ mysql_rec + templ->mysql_col_offset,
+ templ->mysql_col_len, NULL,
+ 0, templ->type, templ->is_unsigned);
+ }
+
if (!templ->mysql_null_bit_mask) {
fprintf(stderr,
"InnoDB: Error: trying to return an SQL NULL field in a non-null\n"
@@ -2369,6 +2383,7 @@ row_sel_push_cache_row_for_mysql(
ulint i;
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
+ ut_a(!prebuilt->templ_contains_blob);
if (prebuilt->fetch_cache[0] == NULL) {
/* Allocate memory for the fetch cache */
@@ -2409,6 +2424,7 @@ row_sel_try_search_shortcut_for_mysql(
rec_t* rec;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(!prebuilt->templ_contains_blob);
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur,
@@ -2591,8 +2607,16 @@ row_search_for_mysql(
mtr_start(&mtr);
- if (match_mode == ROW_SEL_EXACT && index->type & DICT_UNIQUE
+ /* Since we must release the search system latch when we retrieve an
+ externally stored field, we cannot use the adaptive hash index in a
+ search in the case the row may be long and there may be externally
+ stored fields */
+
+ if (match_mode == ROW_SEL_EXACT
+ && index->type & DICT_UNIQUE
&& index->type & DICT_CLUSTERED
+ && !prebuilt->templ_contains_blob
+ && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)
&& dtuple_get_n_fields(search_tuple)
== dict_index_get_n_unique(index)) {
@@ -2945,15 +2969,18 @@ rec_loop:
/* We found a qualifying row */
if (prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD
- && !prebuilt->templ_contains_blob
&& prebuilt->select_lock_type == LOCK_NONE
+ && !prebuilt->templ_contains_blob
&& !prebuilt->clust_index_was_generated
&& prebuilt->template_type
!= ROW_MYSQL_DUMMY_TEMPLATE) {
/* Inside an update, for example, we do not cache rows,
since we may use the cursor position to do the actual
- update, that is why we require ...lock_type == LOCK_NONE */
+ update, that is why we require ...lock_type == LOCK_NONE.
+ Since we keep space in prebuilt only for the BLOBs of
+ a single row, we cannot cache rows in the case there
+ are BLOBs in the fields to be fetched. */
row_sel_push_cache_row_for_mysql(prebuilt, rec);