List:Commits« Previous MessageNext Message »
From:marko.makela Date:April 21 2010 9:50am
Subject:bzr commit into mysql-5.1-innodb branch (marko.makela:3410) Bug#52745
View as plain text  
#At file:///home/marko/innobase/dev/mysql/5.1-innodb/ based on revid:marko.makela@strippedk46qvg2ywn

 3410 Marko Mäkelä	2010-04-21
      dtuple_convert_big_rec(): Store locally any fields whose maximum length
      is less than 256 bytes. (Bug #52745)
      Add related comments and debug assertions to the "offsets"
      functions in rem0rec.c.
      Approved by Sunny Bains

    modified:
      storage/innodb_plugin/ChangeLog
      storage/innodb_plugin/data/data0data.c
      storage/innodb_plugin/rem/rem0rec.c
=== modified file 'storage/innodb_plugin/ChangeLog'
--- a/storage/innodb_plugin/ChangeLog	2010-04-20 11:42:22 +0000
+++ b/storage/innodb_plugin/ChangeLog	2010-04-21 09:50:33 +0000
@@ -1,3 +1,8 @@
+2010-04-21	The InnoDB Team
+
+	* data/data0data.c:
+	Fix Bug#52745 Failing assertion: blob_no < page_zip->n_blobs
+
 2010-04-20	The InnoDB Team
 
 	* dict/dict0crea.c, handler/ha_innodb.cc, include/trx0trx.h:

=== modified file 'storage/innodb_plugin/data/data0data.c'
--- a/storage/innodb_plugin/data/data0data.c	2009-05-25 12:09:24 +0000
+++ b/storage/innodb_plugin/data/data0data.c	2010-04-21 09:50:33 +0000
@@ -666,6 +666,21 @@ dtuple_convert_big_rec(
 				goto skip_field;
 			}
 
+			/* In DYNAMIC and COMPRESSED format, store
+			locally any non-BLOB columns whose maximum
+			length does not exceed 256 bytes.  This is
+			because there is no room for the "external
+			storage" flag when the maximum length is 255
+			bytes or less. This restriction trivially
+			holds in REDUNDANT and COMPACT format, because
+			there we always store locally columns whose
+			length is up to local_len == 788 bytes.
+			@see rec_init_offsets_comp_ordinary */
+			if (ifield->col->mtype != DATA_BLOB
+			    && ifield->col->len < 256) {
+				goto skip_field;
+			}
+
 			longest_i = i;
 			longest = savings;
 

=== modified file 'storage/innodb_plugin/rem/rem0rec.c'
--- a/storage/innodb_plugin/rem/rem0rec.c	2010-04-21 09:16:11 +0000
+++ b/storage/innodb_plugin/rem/rem0rec.c	2010-04-21 09:50:33 +0000
@@ -212,6 +212,13 @@ rec_get_n_extern_new(
 			const dict_col_t*	col
 				= dict_field_get_col(field);
 			len = *lens--;
+			/* If the maximum length of the field is up
+			to 255 bytes, the actual length is always
+			stored in one byte. If the maximum length is
+			more than 255 bytes, the actual length is
+			stored in one byte for 0..127.  The length
+			will be encoded in two bytes when it is 128 or
+			more, or when the field is stored externally. */
 			if (UNIV_UNLIKELY(col->len > 255)
 			    || UNIV_UNLIKELY(col->mtype == DATA_BLOB)) {
 				if (len & 0x80) {
@@ -294,6 +301,13 @@ rec_init_offsets_comp_ordinary(
 			const dict_col_t*	col
 				= dict_field_get_col(field);
 			len = *lens--;
+			/* If the maximum length of the field is up
+			to 255 bytes, the actual length is always
+			stored in one byte. If the maximum length is
+			more than 255 bytes, the actual length is
+			stored in one byte for 0..127.  The length
+			will be encoded in two bytes when it is 128 or
+			more, or when the field is stored externally. */
 			if (UNIV_UNLIKELY(col->len > 255)
 			    || UNIV_UNLIKELY(col->mtype
 					     == DATA_BLOB)) {
@@ -425,6 +439,15 @@ rec_init_offsets(
 				const dict_col_t*	col
 					= dict_field_get_col(field);
 				len = *lens--;
+				/* If the maximum length of the field
+				is up to 255 bytes, the actual length
+				is always stored in one byte. If the
+				maximum length is more than 255 bytes,
+				the actual length is stored in one
+				byte for 0..127.  The length will be
+				encoded in two bytes when it is 128 or
+				more, or when the field is stored
+				externally. */
 				if (UNIV_UNLIKELY(col->len > 255)
 				    || UNIV_UNLIKELY(col->mtype
 						     == DATA_BLOB)) {
@@ -647,6 +670,13 @@ rec_get_offsets_reverse(
 			const dict_col_t*	col
 				= dict_field_get_col(field);
 			len = *lens++;
+			/* If the maximum length of the field is up
+			to 255 bytes, the actual length is always
+			stored in one byte. If the maximum length is
+			more than 255 bytes, the actual length is
+			stored in one byte for 0..127.  The length
+			will be encoded in two bytes when it is 128 or
+			more, or when the field is stored externally. */
 			if (UNIV_UNLIKELY(col->len > 255)
 			    || UNIV_UNLIKELY(col->mtype == DATA_BLOB)) {
 				if (len & 0x80) {
@@ -781,12 +811,20 @@ rec_get_converted_size_comp_prefix(
 
 		ut_ad(len <= col->len || col->mtype == DATA_BLOB);
 
+		/* If the maximum length of a variable-length field
+		is up to 255 bytes, the actual length is always stored
+		in one byte. If the maximum length is more than 255
+		bytes, the actual length is stored in one byte for
+		0..127.  The length will be encoded in two bytes when
+		it is 128 or more, or when the field is stored externally. */
+
 		if (field->fixed_len) {
 			ut_ad(len == field->fixed_len);
 			/* dict_index_add_col() should guarantee this */
 			ut_ad(!field->prefix_len
 			      || field->fixed_len == field->prefix_len);
 		} else if (dfield_is_ext(&fields[i])) {
+			ut_ad(col->len >= 256 || col->mtype == DATA_BLOB);
 			extra_size += 2;
 		} else if (len < 128
 			   || (col->len < 256 && col->mtype != DATA_BLOB)) {
@@ -1086,6 +1124,8 @@ rec_convert_dtuple_to_rec_comp(
 	/* Store the data and the offsets */
 
 	for (i = 0, field = fields; i < n_fields; i++, field++) {
+		const dict_field_t*	ifield;
+
 		type = dfield_get_type(field);
 		len = dfield_get_len(field);
 
@@ -1120,12 +1160,20 @@ rec_convert_dtuple_to_rec_comp(
 		/* only nullable fields can be null */
 		ut_ad(!dfield_is_null(field));
 
-		fixed_len = dict_index_get_nth_field(index, i)->fixed_len;
-
+		ifield = dict_index_get_nth_field(index, i);
+		fixed_len = ifield->fixed_len;
+		/* If the maximum length of a variable-length field
+		is up to 255 bytes, the actual length is always stored
+		in one byte. If the maximum length is more than 255
+		bytes, the actual length is stored in one byte for
+		0..127.  The length will be encoded in two bytes when
+		it is 128 or more, or when the field is stored externally. */
 		if (fixed_len) {
 			ut_ad(len == fixed_len);
 			ut_ad(!dfield_is_ext(field));
 		} else if (dfield_is_ext(field)) {
+			ut_ad(ifield->col->len >= 256
+			      || ifield->col->mtype == DATA_BLOB);
 			ut_ad(len <= REC_MAX_INDEX_COL_LEN
 			      + BTR_EXTERN_FIELD_REF_SIZE);
 			*lens-- = (byte) (len >> 8) | 0xc0;
@@ -1411,6 +1459,13 @@ rec_copy_prefix_to_buf(
 			prefix_len += field->fixed_len;
 		} else {
 			ulint	len = *lens--;
+			/* If the maximum length of the column is up
+			to 255 bytes, the actual length is always
+			stored in one byte. If the maximum length is
+			more than 255 bytes, the actual length is
+			stored in one byte for 0..127.  The length
+			will be encoded in two bytes when it is 128 or
+			more, or when the column is stored externally. */
 			if (col->len > 255 || col->mtype == DATA_BLOB) {
 				if (len & 0x80) {
 					/* 1exxxxxx */

Attachment: [text/bzr-bundle] bzr/marko.makela@oracle.com-20100421095033-0acvzxb8um8cms0a.bundle
Thread
bzr commit into mysql-5.1-innodb branch (marko.makela:3410) Bug#52745marko.makela21 Apr