summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMySQL Build Team <build@mysql.com>2010-06-22 21:59:35 +0200
committerMySQL Build Team <build@mysql.com>2010-06-22 21:59:35 +0200
commitf5a0316a3962ce34f3586574be5598d2bacd5ccb (patch)
treefe4b0614e72d2740636ef26faf4300b49ab402ce
parente87a2d917b39043ce7124aae8788e8247e611211 (diff)
downloadmariadb-git-f5a0316a3962ce34f3586574be5598d2bacd5ccb.tar.gz
Backport into build-201006221614-5.1.46sp1
> ------------------------------------------------------------ > revno: 3351.14.47 > revision-id: marko.makela@oracle.com-20100421095033-0acvzxb8um8cms0a > parent: marko.makela@oracle.com-20100421094032-ir4glqk46qvg2ywn > committer: Marko Mäkelä <marko.makela@oracle.com> > branch nick: 5.1-innodb > timestamp: Wed 2010-04-21 12:50:33 +0300 > message: > 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
-rw-r--r--storage/innodb_plugin/data/data0data.c15
-rw-r--r--storage/innodb_plugin/rem/rem0rec.c59
2 files changed, 72 insertions, 2 deletions
diff --git a/storage/innodb_plugin/data/data0data.c b/storage/innodb_plugin/data/data0data.c
index e3c1f1b4f23..0715b49bf9c 100644
--- a/storage/innodb_plugin/data/data0data.c
+++ b/storage/innodb_plugin/data/data0data.c
@@ -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;
diff --git a/storage/innodb_plugin/rem/rem0rec.c b/storage/innodb_plugin/rem/rem0rec.c
index 27c11dacc8c..59cf6e887d1 100644
--- a/storage/innodb_plugin/rem/rem0rec.c
+++ b/storage/innodb_plugin/rem/rem0rec.c
@@ -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;
@@ -1402,6 +1450,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 */