~ubuntu-branches/debian/squeeze/mysql-5.1/squeeze

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/rem/rem0rec.c

  • Committer: Package Import Robot
  • Author(s): Moritz Muehlenhoff
  • Date: 2014-01-14 10:40:30 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20140114104030-44alii0hx3x3g41y
Tags: 5.1.73-1
* New upstream release
  http://dev.mysql.com/doc/relnotes/mysql/5.1/en/news-5-1-73.html
* Update patches
* Disable flaky test rpl.rpl_innodb_bug28430 breaking the build. It's  marked
  as experimental by upstream and the internet is full of reports about it's
  unrelialibity

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
12
 
13
13
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
 
Place, Suite 330, Boston, MA 02111-1307 USA
 
14
this program; if not, write to the Free Software Foundation, Inc., 
 
15
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
*****************************************************************************/
18
18
 
167
167
{
168
168
        const byte*     nulls;
169
169
        const byte*     lens;
170
 
        dict_field_t*   field;
171
170
        ulint           null_mask;
172
171
        ulint           n_extern;
173
172
        ulint           i;
188
187
 
189
188
        /* read the lengths of fields 0..n */
190
189
        do {
191
 
                ulint   len;
 
190
                const dict_field_t*     field
 
191
                        = dict_index_get_nth_field(index, i);
 
192
                const dict_col_t*       col
 
193
                        = dict_field_get_col(field);
 
194
                ulint                   len;
192
195
 
193
 
                field = dict_index_get_nth_field(index, i);
194
 
                if (!(dict_field_get_col(field)->prtype & DATA_NOT_NULL)) {
 
196
                if (!(col->prtype & DATA_NOT_NULL)) {
195
197
                        /* nullable field => read the null flag */
196
198
 
197
199
                        if (UNIV_UNLIKELY(!(byte) null_mask)) {
209
211
 
210
212
                if (UNIV_UNLIKELY(!field->fixed_len)) {
211
213
                        /* Variable-length field: read the length */
212
 
                        const dict_col_t*       col
213
 
                                = dict_field_get_col(field);
214
214
                        len = *lens--;
215
215
                        /* If the maximum length of the field is up
216
216
                        to 255 bytes, the actual length is always
239
239
Determine the offset to each field in a leaf-page record
240
240
in ROW_FORMAT=COMPACT.  This is a special case of
241
241
rec_init_offsets() and rec_get_offsets_func(). */
242
 
UNIV_INTERN
 
242
UNIV_INLINE __attribute__((nonnull))
243
243
void
244
244
rec_init_offsets_comp_ordinary(
245
245
/*===========================*/
246
246
        const rec_t*            rec,    /*!< in: physical record in
247
247
                                        ROW_FORMAT=COMPACT */
248
 
        ulint                   extra,  /*!< in: number of bytes to reserve
249
 
                                        between the record header and
250
 
                                        the data payload
251
 
                                        (usually REC_N_NEW_EXTRA_BYTES) */
 
248
        ibool                   temp,   /*!< in: whether to use the
 
249
                                        format for temporary files in
 
250
                                        index creation */
252
251
        const dict_index_t*     index,  /*!< in: record descriptor */
253
252
        ulint*                  offsets)/*!< in/out: array of offsets;
254
253
                                        in: n=rec_offs_n_fields(offsets) */
256
255
        ulint           i               = 0;
257
256
        ulint           offs            = 0;
258
257
        ulint           any_ext         = 0;
259
 
        const byte*     nulls           = rec - (extra + 1);
 
258
        const byte*     nulls           = temp
 
259
                ? rec - 1
 
260
                : rec - (1 + REC_N_NEW_EXTRA_BYTES);
260
261
        const byte*     lens            = nulls
261
262
                - UT_BITS_IN_BYTES(index->n_nullable);
262
 
        dict_field_t*   field;
263
263
        ulint           null_mask       = 1;
264
264
 
265
265
#ifdef UNIV_DEBUG
266
 
        /* We cannot invoke rec_offs_make_valid() here, because it can hold
267
 
        that extra != REC_N_NEW_EXTRA_BYTES.  Similarly, rec_offs_validate()
268
 
        will fail in that case, because it invokes rec_get_status(). */
 
266
        /* We cannot invoke rec_offs_make_valid() here if temp=TRUE.
 
267
        Similarly, rec_offs_validate() will fail in that case, because
 
268
        it invokes rec_get_status(). */
269
269
        offsets[2] = (ulint) rec;
270
270
        offsets[3] = (ulint) index;
271
271
#endif /* UNIV_DEBUG */
272
272
 
 
273
        ut_ad(temp || dict_table_is_comp(index->table));
 
274
 
 
275
        if (temp && dict_table_is_comp(index->table)) {
 
276
                /* No need to do adjust fixed_len=0. We only need to
 
277
                adjust it for ROW_FORMAT=REDUNDANT. */
 
278
                temp = FALSE;
 
279
        }
 
280
 
273
281
        /* read the lengths of fields 0..n */
274
282
        do {
275
 
                ulint   len;
 
283
                const dict_field_t*     field
 
284
                        = dict_index_get_nth_field(index, i);
 
285
                const dict_col_t*       col
 
286
                        = dict_field_get_col(field);
 
287
                ulint                   len;
276
288
 
277
 
                field = dict_index_get_nth_field(index, i);
278
 
                if (!(dict_field_get_col(field)->prtype
279
 
                      & DATA_NOT_NULL)) {
 
289
                if (!(col->prtype & DATA_NOT_NULL)) {
280
290
                        /* nullable field => read the null flag */
281
291
 
282
292
                        if (UNIV_UNLIKELY(!(byte) null_mask)) {
296
306
                        null_mask <<= 1;
297
307
                }
298
308
 
299
 
                if (UNIV_UNLIKELY(!field->fixed_len)) {
 
309
                if (!field->fixed_len
 
310
                    || (temp && !dict_col_get_fixed_size(col, temp))) {
300
311
                        /* Variable-length field: read the length */
301
 
                        const dict_col_t*       col
302
 
                                = dict_field_get_col(field);
303
312
                        len = *lens--;
304
313
                        /* If the maximum length of the field is up
305
314
                        to 255 bytes, the actual length is always
393
402
                                = dict_index_get_n_unique_in_tree(index);
394
403
                        break;
395
404
                case REC_STATUS_ORDINARY:
396
 
                        rec_init_offsets_comp_ordinary(rec,
397
 
                                                       REC_N_NEW_EXTRA_BYTES,
398
 
                                                       index, offsets);
 
405
                        rec_init_offsets_comp_ordinary(
 
406
                                rec, FALSE, index, offsets);
399
407
                        return;
400
408
                }
401
409
 
408
416
                do {
409
417
                        ulint   len;
410
418
                        if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
411
 
                                len = offs += 4;
 
419
                                len = offs += REC_NODE_PTR_SIZE;
412
420
                                goto resolved;
413
421
                        }
414
422
 
640
648
        do {
641
649
                ulint   len;
642
650
                if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
643
 
                        len = offs += 4;
 
651
                        len = offs += REC_NODE_PTR_SIZE;
644
652
                        goto resolved;
645
653
                }
646
654
 
766
774
/**********************************************************//**
767
775
Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT.
768
776
@return total size */
769
 
UNIV_INTERN
 
777
UNIV_INLINE __attribute__((warn_unused_result, nonnull(1,2)))
770
778
ulint
771
 
rec_get_converted_size_comp_prefix(
772
 
/*===============================*/
 
779
rec_get_converted_size_comp_prefix_low(
 
780
/*===================================*/
773
781
        const dict_index_t*     index,  /*!< in: record descriptor;
774
782
                                        dict_table_is_comp() is
775
783
                                        assumed to hold, even if
776
784
                                        it does not */
777
785
        const dfield_t*         fields, /*!< in: array of data fields */
778
786
        ulint                   n_fields,/*!< in: number of data fields */
779
 
        ulint*                  extra)  /*!< out: extra size */
 
787
        ulint*                  extra,  /*!< out: extra size */
 
788
        ibool                   temp)   /*!< in: whether this is a
 
789
                                        temporary file record */
780
790
{
781
791
        ulint   extra_size;
782
792
        ulint   data_size;
785
795
        ut_ad(fields);
786
796
        ut_ad(n_fields > 0);
787
797
        ut_ad(n_fields <= dict_index_get_n_fields(index));
 
798
        ut_ad(!temp || extra);
788
799
 
789
 
        extra_size = REC_N_NEW_EXTRA_BYTES
 
800
        extra_size = temp
 
801
                ? UT_BITS_IN_BYTES(index->n_nullable)
 
802
                : REC_N_NEW_EXTRA_BYTES
790
803
                + UT_BITS_IN_BYTES(index->n_nullable);
791
804
        data_size = 0;
792
805
 
 
806
        if (temp && dict_table_is_comp(index->table)) {
 
807
                /* No need to do adjust fixed_len=0. We only need to
 
808
                adjust it for ROW_FORMAT=REDUNDANT. */
 
809
                temp = FALSE;
 
810
        }
 
811
 
793
812
        /* read the lengths of fields 0..n */
794
813
        for (i = 0; i < n_fields; i++) {
795
814
                const dict_field_t*     field;
796
815
                ulint                   len;
 
816
                ulint                   fixed_len;
797
817
                const dict_col_t*       col;
798
818
 
799
819
                field = dict_index_get_nth_field(index, i);
809
829
                        continue;
810
830
                }
811
831
 
812
 
                ut_ad(len <= col->len || col->mtype == DATA_BLOB);
 
832
                ut_ad(len <= col->len || col->mtype == DATA_BLOB
 
833
                      || (col->len == 0 && col->mtype == DATA_VARCHAR));
813
834
 
 
835
                fixed_len = field->fixed_len;
 
836
                if (temp && fixed_len
 
837
                    && !dict_col_get_fixed_size(col, temp)) {
 
838
                        fixed_len = 0;
 
839
                }
814
840
                /* If the maximum length of a variable-length field
815
841
                is up to 255 bytes, the actual length is always stored
816
842
                in one byte. If the maximum length is more than 255
818
844
                0..127.  The length will be encoded in two bytes when
819
845
                it is 128 or more, or when the field is stored externally. */
820
846
 
821
 
                if (field->fixed_len) {
822
 
                        ut_ad(len == field->fixed_len);
 
847
                if (fixed_len) {
 
848
                        ut_ad(len == fixed_len);
823
849
                        /* dict_index_add_col() should guarantee this */
824
850
                        ut_ad(!field->prefix_len
825
 
                              || field->fixed_len == field->prefix_len);
 
851
                              || fixed_len == field->prefix_len);
826
852
                } else if (dfield_is_ext(&fields[i])) {
827
853
                        ut_ad(col->len >= 256 || col->mtype == DATA_BLOB);
828
854
                        extra_size += 2;
839
865
                data_size += len;
840
866
        }
841
867
 
842
 
        if (UNIV_LIKELY_NULL(extra)) {
 
868
        if (extra) {
843
869
                *extra = extra_size;
844
870
        }
845
871
 
847
873
}
848
874
 
849
875
/**********************************************************//**
 
876
Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT.
 
877
@return total size */
 
878
UNIV_INTERN
 
879
ulint
 
880
rec_get_converted_size_comp_prefix(
 
881
/*===============================*/
 
882
        const dict_index_t*     index,  /*!< in: record descriptor */
 
883
        const dfield_t*         fields, /*!< in: array of data fields */
 
884
        ulint                   n_fields,/*!< in: number of data fields */
 
885
        ulint*                  extra)  /*!< out: extra size */
 
886
{
 
887
        ut_ad(dict_table_is_comp(index->table));
 
888
        return(rec_get_converted_size_comp_prefix_low(
 
889
                       index, fields, n_fields, extra, FALSE));
 
890
}
 
891
 
 
892
/**********************************************************//**
850
893
Determines the size of a data tuple in ROW_FORMAT=COMPACT.
851
894
@return total size */
852
895
UNIV_INTERN
890
933
                return(ULINT_UNDEFINED);
891
934
        }
892
935
 
893
 
        return(size + rec_get_converted_size_comp_prefix(index, fields,
894
 
                                                         n_fields, extra));
 
936
        return(size + rec_get_converted_size_comp_prefix_low(
 
937
                       index, fields, n_fields, extra, FALSE));
895
938
}
896
939
 
897
940
/***********************************************************//**
1068
1111
 
1069
1112
/*********************************************************//**
1070
1113
Builds a ROW_FORMAT=COMPACT record out of a data tuple. */
1071
 
UNIV_INTERN
 
1114
UNIV_INLINE __attribute__((nonnull))
1072
1115
void
1073
1116
rec_convert_dtuple_to_rec_comp(
1074
1117
/*===========================*/
1075
1118
        rec_t*                  rec,    /*!< in: origin of record */
1076
 
        ulint                   extra,  /*!< in: number of bytes to
1077
 
                                        reserve between the record
1078
 
                                        header and the data payload
1079
 
                                        (normally REC_N_NEW_EXTRA_BYTES) */
1080
1119
        const dict_index_t*     index,  /*!< in: record descriptor */
 
1120
        const dfield_t*         fields, /*!< in: array of data fields */
 
1121
        ulint                   n_fields,/*!< in: number of data fields */
1081
1122
        ulint                   status, /*!< in: status bits of the record */
1082
 
        const dfield_t*         fields, /*!< in: array of data fields */
1083
 
        ulint                   n_fields)/*!< in: number of data fields */
 
1123
        ibool                   temp)   /*!< in: whether to use the
 
1124
                                        format for temporary files in
 
1125
                                        index creation */
1084
1126
{
1085
1127
        const dfield_t* field;
1086
1128
        const dtype_t*  type;
1092
1134
        ulint           n_node_ptr_field;
1093
1135
        ulint           fixed_len;
1094
1136
        ulint           null_mask       = 1;
1095
 
        ut_ad(extra == 0 || dict_table_is_comp(index->table));
1096
 
        ut_ad(extra == 0 || extra == REC_N_NEW_EXTRA_BYTES);
 
1137
        ut_ad(temp || dict_table_is_comp(index->table));
1097
1138
        ut_ad(n_fields > 0);
1098
1139
 
1099
 
        switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
1100
 
        case REC_STATUS_ORDINARY:
 
1140
        if (temp) {
 
1141
                ut_ad(status == REC_STATUS_ORDINARY);
1101
1142
                ut_ad(n_fields <= dict_index_get_n_fields(index));
1102
1143
                n_node_ptr_field = ULINT_UNDEFINED;
1103
 
                break;
1104
 
        case REC_STATUS_NODE_PTR:
1105
 
                ut_ad(n_fields == dict_index_get_n_unique_in_tree(index) + 1);
1106
 
                n_node_ptr_field = n_fields - 1;
1107
 
                break;
1108
 
        case REC_STATUS_INFIMUM:
1109
 
        case REC_STATUS_SUPREMUM:
1110
 
                ut_ad(n_fields == 1);
1111
 
                n_node_ptr_field = ULINT_UNDEFINED;
1112
 
                break;
1113
 
        default:
1114
 
                ut_error;
1115
 
                return;
 
1144
                nulls = rec - 1;
 
1145
                if (dict_table_is_comp(index->table)) {
 
1146
                        /* No need to do adjust fixed_len=0. We only
 
1147
                        need to adjust it for ROW_FORMAT=REDUNDANT. */
 
1148
                        temp = FALSE;
 
1149
                }
 
1150
        } else {
 
1151
                nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
 
1152
 
 
1153
                switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
 
1154
                case REC_STATUS_ORDINARY:
 
1155
                        ut_ad(n_fields <= dict_index_get_n_fields(index));
 
1156
                        n_node_ptr_field = ULINT_UNDEFINED;
 
1157
                        break;
 
1158
                case REC_STATUS_NODE_PTR:
 
1159
                        ut_ad(n_fields
 
1160
                              == dict_index_get_n_unique_in_tree(index) + 1);
 
1161
                        n_node_ptr_field = n_fields - 1;
 
1162
                        break;
 
1163
                case REC_STATUS_INFIMUM:
 
1164
                case REC_STATUS_SUPREMUM:
 
1165
                        ut_ad(n_fields == 1);
 
1166
                        n_node_ptr_field = ULINT_UNDEFINED;
 
1167
                        break;
 
1168
                default:
 
1169
                        ut_error;
 
1170
                        return;
 
1171
                }
1116
1172
        }
1117
1173
 
1118
1174
        end = rec;
1119
 
        nulls = rec - (extra + 1);
1120
1175
        lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
1121
1176
        /* clear the SQL-null flags */
1122
1177
        memset(lens + 1, 0, nulls - lens);
1131
1186
 
1132
1187
                if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
1133
1188
                        ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
1134
 
                        ut_ad(len == 4);
 
1189
                        ut_ad(len == REC_NODE_PTR_SIZE);
1135
1190
                        memcpy(end, dfield_get_data(field), len);
1136
 
                        end += 4;
 
1191
                        end += REC_NODE_PTR_SIZE;
1137
1192
                        break;
1138
1193
                }
1139
1194
 
1162
1217
 
1163
1218
                ifield = dict_index_get_nth_field(index, i);
1164
1219
                fixed_len = ifield->fixed_len;
 
1220
                if (temp && fixed_len
 
1221
                    && !dict_col_get_fixed_size(ifield->col, temp)) {
 
1222
                        fixed_len = 0;
 
1223
                }
1165
1224
                /* If the maximum length of a variable-length field
1166
1225
                is up to 255 bytes, the actual length is always stored
1167
1226
                in one byte. If the maximum length is more than 255
1222
1281
        rec = buf + extra_size;
1223
1282
 
1224
1283
        rec_convert_dtuple_to_rec_comp(
1225
 
                rec, REC_N_NEW_EXTRA_BYTES, index, status,
1226
 
                dtuple->fields, dtuple->n_fields);
 
1284
                rec, index, dtuple->fields, dtuple->n_fields, status, FALSE);
1227
1285
 
1228
1286
        /* Set the info bits of the record */
1229
1287
        rec_set_info_and_status_bits(rec, dtuple_get_info_bits(dtuple));
1285
1343
        return(rec);
1286
1344
}
1287
1345
 
 
1346
#ifndef UNIV_HOTBACKUP
 
1347
/**********************************************************//**
 
1348
Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT.
 
1349
@return total size */
 
1350
UNIV_INTERN
 
1351
ulint
 
1352
rec_get_converted_size_temp(
 
1353
/*========================*/
 
1354
        const dict_index_t*     index,  /*!< in: record descriptor */
 
1355
        const dfield_t*         fields, /*!< in: array of data fields */
 
1356
        ulint                   n_fields,/*!< in: number of data fields */
 
1357
        ulint*                  extra)  /*!< out: extra size */
 
1358
{
 
1359
        return(rec_get_converted_size_comp_prefix_low(
 
1360
                       index, fields, n_fields, extra, TRUE));
 
1361
}
 
1362
 
 
1363
/******************************************************//**
 
1364
Determine the offset to each field in temporary file.
 
1365
@see rec_convert_dtuple_to_temp() */
 
1366
UNIV_INTERN
 
1367
void
 
1368
rec_init_offsets_temp(
 
1369
/*==================*/
 
1370
        const rec_t*            rec,    /*!< in: temporary file record */
 
1371
        const dict_index_t*     index,  /*!< in: record descriptor */
 
1372
        ulint*                  offsets)/*!< in/out: array of offsets;
 
1373
                                        in: n=rec_offs_n_fields(offsets) */
 
1374
{
 
1375
        rec_init_offsets_comp_ordinary(rec, TRUE, index, offsets);
 
1376
}
 
1377
 
 
1378
/*********************************************************//**
 
1379
Builds a temporary file record out of a data tuple.
 
1380
@see rec_init_offsets_temp() */
 
1381
UNIV_INTERN
 
1382
void
 
1383
rec_convert_dtuple_to_temp(
 
1384
/*=======================*/
 
1385
        rec_t*                  rec,            /*!< out: record */
 
1386
        const dict_index_t*     index,          /*!< in: record descriptor */
 
1387
        const dfield_t*         fields,         /*!< in: array of data fields */
 
1388
        ulint                   n_fields)       /*!< in: number of fields */
 
1389
{
 
1390
        rec_convert_dtuple_to_rec_comp(rec, index, fields, n_fields,
 
1391
                                       REC_STATUS_ORDINARY, TRUE);
 
1392
}
 
1393
 
1288
1394
/**************************************************************//**
1289
1395
Copies the first n fields of a physical record to a data tuple. The fields
1290
1396
are copied to the memory heap. */
1495
1601
 
1496
1602
        return(*buf + (rec - (lens + 1)));
1497
1603
}
 
1604
#endif /* UNIV_HOTBACKUP */
1498
1605
 
1499
1606
/***************************************************************//**
1500
1607
Validates the consistency of an old-style physical record.