1
1
/*****************************************************************************
3
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
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.
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
17
17
*****************************************************************************/
189
188
/* read the lengths of fields 0..n */
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);
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 */
197
199
if (UNIV_UNLIKELY(!(byte) null_mask)) {
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);
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_INLINE __attribute__((nonnull))
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
251
(usually REC_N_NEW_EXTRA_BYTES) */
248
ibool temp, /*!< in: whether to use the
249
format for temporary files in
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) */
258
257
ulint any_ext = 0;
259
const byte* nulls = rec - (extra + 1);
258
const byte* nulls = temp
260
: rec - (1 + REC_N_NEW_EXTRA_BYTES);
260
261
const byte* lens = nulls
261
262
- UT_BITS_IN_BYTES(index->n_nullable);
263
263
ulint null_mask = 1;
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 */
273
ut_ad(temp || dict_table_is_comp(index->table));
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. */
273
281
/* read the lengths of fields 0..n */
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);
277
field = dict_index_get_nth_field(index, i);
278
if (!(dict_field_get_col(field)->prtype
289
if (!(col->prtype & DATA_NOT_NULL)) {
280
290
/* nullable field => read the null flag */
282
292
if (UNIV_UNLIKELY(!(byte) null_mask)) {
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);
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);
395
404
case REC_STATUS_ORDINARY:
396
rec_init_offsets_comp_ordinary(rec,
397
REC_N_NEW_EXTRA_BYTES,
405
rec_init_offsets_comp_ordinary(
406
rec, FALSE, index, offsets);
766
774
/**********************************************************//**
767
775
Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT.
768
776
@return total size */
777
UNIV_INLINE __attribute__((warn_unused_result, nonnull(1,2)))
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
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 */
781
791
ulint extra_size;
786
796
ut_ad(n_fields > 0);
787
797
ut_ad(n_fields <= dict_index_get_n_fields(index));
798
ut_ad(!temp || extra);
789
extra_size = REC_N_NEW_EXTRA_BYTES
801
? UT_BITS_IN_BYTES(index->n_nullable)
802
: REC_N_NEW_EXTRA_BYTES
790
803
+ UT_BITS_IN_BYTES(index->n_nullable);
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. */
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;
797
817
const dict_col_t* col;
799
819
field = dict_index_get_nth_field(index, i);
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));
835
fixed_len = field->fixed_len;
836
if (temp && fixed_len
837
&& !dict_col_get_fixed_size(col, temp)) {
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. */
821
if (field->fixed_len) {
822
ut_ad(len == field->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);
849
875
/**********************************************************//**
876
Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT.
877
@return total size */
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 */
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));
892
/**********************************************************//**
850
893
Determines the size of a data tuple in ROW_FORMAT=COMPACT.
851
894
@return total size */
890
933
return(ULINT_UNDEFINED);
893
return(size + rec_get_converted_size_comp_prefix(index, fields,
936
return(size + rec_get_converted_size_comp_prefix_low(
937
index, fields, n_fields, extra, FALSE));
897
940
/***********************************************************//**
1069
1112
/*********************************************************//**
1070
1113
Builds a ROW_FORMAT=COMPACT record out of a data tuple. */
1114
UNIV_INLINE __attribute__((nonnull))
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
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);
1099
switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
1100
case REC_STATUS_ORDINARY:
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;
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;
1108
case REC_STATUS_INFIMUM:
1109
case REC_STATUS_SUPREMUM:
1110
ut_ad(n_fields == 1);
1111
n_node_ptr_field = ULINT_UNDEFINED;
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. */
1151
nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
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;
1158
case REC_STATUS_NODE_PTR:
1160
== dict_index_get_n_unique_in_tree(index) + 1);
1161
n_node_ptr_field = n_fields - 1;
1163
case REC_STATUS_INFIMUM:
1164
case REC_STATUS_SUPREMUM:
1165
ut_ad(n_fields == 1);
1166
n_node_ptr_field = ULINT_UNDEFINED;
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);
1132
1187
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
1133
1188
ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
1189
ut_ad(len == REC_NODE_PTR_SIZE);
1135
1190
memcpy(end, dfield_get_data(field), len);
1191
end += REC_NODE_PTR_SIZE;
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)) {
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;
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);
1228
1286
/* Set the info bits of the record */
1229
1287
rec_set_info_and_status_bits(rec, dtuple_get_info_bits(dtuple));
1346
#ifndef UNIV_HOTBACKUP
1347
/**********************************************************//**
1348
Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT.
1349
@return total size */
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 */
1359
return(rec_get_converted_size_comp_prefix_low(
1360
index, fields, n_fields, extra, TRUE));
1363
/******************************************************//**
1364
Determine the offset to each field in temporary file.
1365
@see rec_convert_dtuple_to_temp() */
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) */
1375
rec_init_offsets_comp_ordinary(rec, TRUE, index, offsets);
1378
/*********************************************************//**
1379
Builds a temporary file record out of a data tuple.
1380
@see rec_init_offsets_temp() */
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 */
1390
rec_convert_dtuple_to_rec_comp(rec, index, fields, n_fields,
1391
REC_STATUS_ORDINARY, TRUE);
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. */