diff options
author | Timothy Smith <timothy.smith@sun.com> | 2009-03-02 18:00:23 -0700 |
---|---|---|
committer | Timothy Smith <timothy.smith@sun.com> | 2009-03-02 18:00:23 -0700 |
commit | 62d5d85c5d19b113b772ecadbf32f198831b543b (patch) | |
tree | 571e8b01ca818e22143664ba3098c33bb1fbca79 /innobase | |
parent | c3fec5d22ff38388f68718bf77cca183778978a1 (diff) | |
download | mariadb-git-62d5d85c5d19b113b772ecadbf32f198831b543b.tar.gz |
Applying InnoDB snashot 5.0-ss4007, part 3. Fixes
Bug #41571: MySQL segfaults after innodb recovery
This 5.0 fix will not be pushed into 5.1; a separate fix (from
innodb-5.1-ss4007) will be pushed into 5.1+.
Detailed revision comments:
r4003 | marko | 2009-01-20 16:12:50 +0200 (Tue, 20 Jan 2009) | 10 lines
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
Diffstat (limited to 'innobase')
-rw-r--r-- | innobase/include/rem0rec.h | 11 | ||||
-rw-r--r-- | innobase/include/rem0rec.ic | 19 |
2 files changed, 13 insertions, 17 deletions
diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h index 69b397c9682..b573c5d4c3b 100644 --- a/innobase/include/rem0rec.h +++ b/innobase/include/rem0rec.h @@ -368,8 +368,9 @@ rec_set_field_extern_bits( /*************************************************************** 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 -is UNIV_SQL_NULL then the field is treated as an SQL null for old-style -records. For new-style records, len must not be UNIV_SQL_NULL. */ +is UNIV_SQL_NULL then the field is treated as an 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 void rec_set_nth_field( @@ -378,11 +379,7 @@ rec_set_nth_field( const ulint* offsets,/* in: array returned by rec_get_offsets() */ ulint n, /* in: index number of the field */ const void* data, /* in: pointer to the data if not 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. */ + ulint len); /* in: length of the data or UNIV_SQL_NULL */ /************************************************************** The following function returns the data size of an old-style physical record, that is the sum of field lengths. SQL null fields diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index 1abbb503bab..64c91724386 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -1204,8 +1204,9 @@ rec_get_nth_field_size( /*************************************************************** 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 -is UNIV_SQL_NULL then the field is treated as an SQL null for old-style -records. For new-style records, len must not be UNIV_SQL_NULL. */ +is UNIV_SQL_NULL then the field is treated as an 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 void rec_set_nth_field( @@ -1215,11 +1216,7 @@ rec_set_nth_field( ulint n, /* in: index number of the field */ const void* data, /* in: pointer to the data if not 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. */ + ulint len) /* in: length of the data or UNIV_SQL_NULL */ { byte* data2; ulint len2; @@ -1227,9 +1224,11 @@ rec_set_nth_field( ut_ad(rec); ut_ad(rec_offs_validate(rec, NULL, offsets)); - if (len == UNIV_SQL_NULL) { - ut_ad(!rec_offs_comp(offsets)); - rec_set_nth_field_sql_null(rec, n); + if (UNIV_UNLIKELY(len == UNIV_SQL_NULL)) { + if (!rec_offs_nth_sql_null(offsets, n)) { + ut_a(!rec_offs_comp(offsets)); + rec_set_nth_field_sql_null(rec, n); + } return; } |