Commit d2e4204a authored by Timothy Smith's avatar Timothy Smith

Applying InnoDB snashot 5.1-ss4007, part 1. Fixes

Bug #41571: MySQL segfaults after innodb recovery

Detailed revision comments:

r4004 | marko | 2009-01-20 16:19:00 +0200 (Tue, 20 Jan 2009) | 12 lines
branches/5.1: Merge r4003 from branches/5.0:

rec_set_nth_field(): When the field already is SQL null,
do nothing when it is being changed to SQL null. (Bug #41571)

Normally, MySQL does not pass "do-nothing" updates to the storage engine.
When it does and a column of an InnoDB table that is in ROW_FORMAT=COMPACT
is being updated from NULL to NULL, the InnoDB buffer pool will be corrupted
without this fix.

rb://81 approved by Heikki Tuuri
parent 39a4ab6c
...@@ -365,8 +365,9 @@ rec_set_field_extern_bits( ...@@ -365,8 +365,9 @@ rec_set_field_extern_bits(
/*************************************************************** /***************************************************************
This is used to modify the value of an already existing field in a record. This is used to modify the value of an already existing field in a record.
The previous value must have exactly the same size as the new value. If len The previous value must have exactly the same size as the new value. If len
is UNIV_SQL_NULL then the field is treated as an SQL null for old-style is UNIV_SQL_NULL then the field is treated as an SQL null.
records. For new-style records, len must not be UNIV_SQL_NULL. */ For records in ROW_FORMAT=COMPACT (new-style records), len must not be
UNIV_SQL_NULL unless the field already is SQL null. */
UNIV_INLINE UNIV_INLINE
void void
rec_set_nth_field( rec_set_nth_field(
...@@ -375,11 +376,7 @@ rec_set_nth_field( ...@@ -375,11 +376,7 @@ rec_set_nth_field(
const ulint* offsets,/* in: array returned by rec_get_offsets() */ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint n, /* in: index number of the field */ ulint n, /* in: index number of the field */
const void* data, /* in: pointer to the data if not SQL null */ const void* data, /* in: pointer to the data if not SQL null */
ulint len); /* in: length of the data or UNIV_SQL_NULL. ulint len); /* in: length of the data or UNIV_SQL_NULL */
If not SQL null, must have the same
length as the previous value.
If SQL null, previous value must be
SQL null. */
/************************************************************** /**************************************************************
The following function returns the data size of an old-style physical The following function returns the data size of an old-style physical
record, that is the sum of field lengths. SQL null fields record, that is the sum of field lengths. SQL null fields
......
...@@ -1219,8 +1219,9 @@ rec_get_nth_field_size( ...@@ -1219,8 +1219,9 @@ rec_get_nth_field_size(
/*************************************************************** /***************************************************************
This is used to modify the value of an already existing field in a record. This is used to modify the value of an already existing field in a record.
The previous value must have exactly the same size as the new value. If len The previous value must have exactly the same size as the new value. If len
is UNIV_SQL_NULL then the field is treated as an SQL null for old-style is UNIV_SQL_NULL then the field is treated as an SQL null.
records. For new-style records, len must not be UNIV_SQL_NULL. */ For records in ROW_FORMAT=COMPACT (new-style records), len must not be
UNIV_SQL_NULL unless the field already is SQL null. */
UNIV_INLINE UNIV_INLINE
void void
rec_set_nth_field( rec_set_nth_field(
...@@ -1230,11 +1231,7 @@ rec_set_nth_field( ...@@ -1230,11 +1231,7 @@ rec_set_nth_field(
ulint n, /* in: index number of the field */ ulint n, /* in: index number of the field */
const void* data, /* in: pointer to the data const void* data, /* in: pointer to the data
if not SQL null */ if not SQL null */
ulint len) /* in: length of the data or UNIV_SQL_NULL. ulint len) /* in: length of the data or UNIV_SQL_NULL */
If not SQL null, must have the same
length as the previous value.
If SQL null, previous value must be
SQL null. */
{ {
byte* data2; byte* data2;
ulint len2; ulint len2;
...@@ -1242,9 +1239,11 @@ rec_set_nth_field( ...@@ -1242,9 +1239,11 @@ rec_set_nth_field(
ut_ad(rec); ut_ad(rec);
ut_ad(rec_offs_validate(rec, NULL, offsets)); ut_ad(rec_offs_validate(rec, NULL, offsets));
if (len == UNIV_SQL_NULL) { if (UNIV_UNLIKELY(len == UNIV_SQL_NULL)) {
ut_ad(!rec_offs_comp(offsets)); if (!rec_offs_nth_sql_null(offsets, n)) {
rec_set_nth_field_sql_null(rec, n); ut_a(!rec_offs_comp(offsets));
rec_set_nth_field_sql_null(rec, n);
}
return; return;
} }
......
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