diff options
author | unknown <monty@hundin.mysql.fi> | 2002-05-16 18:20:49 +0300 |
---|---|---|
committer | unknown <monty@hundin.mysql.fi> | 2002-05-16 18:20:49 +0300 |
commit | 4d094257dbb785d792785e610ab3cdf41eae9b8c (patch) | |
tree | 12de711f3f9d8ad9eee9d28cf71e5487f17315d3 /innobase | |
parent | 2618c6963c5bf1349c47ce3af6e55213ea9773f4 (diff) | |
parent | 74d29a07712a0caf57fca62dacfeb14b110beca4 (diff) | |
download | mariadb-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.c | 12 | ||||
-rw-r--r-- | innobase/row/row0mysql.c | 42 | ||||
-rw-r--r-- | innobase/row/row0sel.c | 41 |
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); |