函数rec_init_offsets

时间:2021-10-12 09:40:56

http://database.51cto.com/art/201303/383042.htm

/******************************************************//**
The following function determines the offsets to each field in the
record.     The offsets are written to a previously allocated array of
ulint, where rec_offs_n_fields(offsets) has been initialized to the
number of fields in the record.     The rest of the array will be
initialized by this function.  rec_offs_base(offsets)[0] will be set
to the extra size (if REC_OFFS_COMPACT is set, the record is in the
new format; if REC_OFFS_EXTERNAL is set, the record contains externally
stored columns), and rec_offs_base(offsets)[1..n_fields] will be set to
offsets past the end of fields 0..n_fields, or to the beginning of
fields 1..n_fields+1.  When the high-order bit of the offset at [i+1]
is set (REC_OFFS_SQL_NULL), the field i is NULL.  When the second
high-order bit of the offset at [i+1] is set (REC_OFFS_EXTERNAL), the
field i is being stored externally. */
static
void
rec_init_offsets(
/*=============*/
    const rec_t*        rec,    /*!< in: physical record */
    const dict_index_t*    index,    /*!< in: record descriptor */
    ulint*            offsets)/*!< in/out: array of offsets;
                    in: n=rec_offs_n_fields(offsets) */
{
    ulint    i    = ;
    ulint    offs;

    rec_offs_make_valid(rec, index, offsets);

    if (dict_table_is_comp(index->table)) {
        const byte*    nulls;
        const byte*    lens;
        dict_field_t*    field;
        ulint        null_mask;
        ulint        status = rec_get_status(rec);
        ulint        n_node_ptr_field = ULINT_UNDEFINED;

        switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
        case REC_STATUS_INFIMUM:
        case REC_STATUS_SUPREMUM:
            /* the field is 8 bytes long */
            rec_offs_base(offsets)[]
                = REC_N_NEW_EXTRA_BYTES | REC_OFFS_COMPACT;
            rec_offs_base(offsets)[] = ;
            return;
        case REC_STATUS_NODE_PTR:
            n_node_ptr_field
                = dict_index_get_n_unique_in_tree(index);
            break;
        case REC_STATUS_ORDINARY:
            rec_init_offsets_comp_ordinary(
                rec, FALSE, index, offsets);
            return;
        }

        nulls = rec - (REC_N_NEW_EXTRA_BYTES + );
        lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
        offs = ;
        null_mask = ;

        /* read the lengths of fields 0..n */
        do {
            ulint    len;
            if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
                len = offs += REC_NODE_PTR_SIZE;
                goto resolved;
            }

            field = dict_index_get_nth_field(index, i);
            if (!(dict_field_get_col(field)->prtype
                  & DATA_NOT_NULL)) {
                /* nullable field => read the null flag */

                if (UNIV_UNLIKELY(!(byte) null_mask)) {
                    nulls--;
                    null_mask = ;
                }

                if (*nulls & null_mask) {
                    null_mask <<= ;
                    /* No length is stored for NULL fields.
                    We do not advance offs, and we set
                    the length to zero and enable the
                    SQL NULL flag in offsets[]. */
                    len = offs | REC_OFFS_SQL_NULL;
                    goto resolved;
                }
                null_mask <<= ;
            }

            if (UNIV_UNLIKELY(!field->fixed_len)) {
                /* Variable-length field: read the length */
                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. */
                )
                    || UNIV_UNLIKELY(col->mtype
                             == DATA_BLOB)) {
                    if (len & 0x80) {
                        /* 1exxxxxxx xxxxxxxx */

                        len <<= ;
                        len |= *lens--;

                        /* B-tree node pointers
                        must not contain externally
                        stored columns.  Thus
                        the "e" flag must be 0. */
                        ut_a(!(len & 0x4000));
                        offs += len & 0x3fff;
                        len = offs;

                        goto resolved;
                    }
                }

                len = offs += len;
            } else {
                len = offs += field->fixed_len;
            }
resolved:
            rec_offs_base(offsets)[i + ] = len;
        } while (++i < rec_offs_n_fields(offsets));

        *rec_offs_base(offsets)
            = (rec - (lens + )) | REC_OFFS_COMPACT;
    } else {
        /* Old-style record: determine extra size and end offsets */
        offs = REC_N_OLD_EXTRA_BYTES;
        if (rec_get_1byte_offs_flag(rec)) {
            offs += rec_offs_n_fields(offsets);
            *rec_offs_base(offsets) = offs;
            /* Determine offsets to fields */
            do {
                offs = rec_1_get_field_end_info(rec, i);
                if (offs & REC_1BYTE_SQL_NULL_MASK) {
                    offs &= ~REC_1BYTE_SQL_NULL_MASK;
                    offs |= REC_OFFS_SQL_NULL;
                }
                rec_offs_base(offsets)[ + i] = offs;
            } while (++i < rec_offs_n_fields(offsets));
        } else {
            offs +=  * rec_offs_n_fields(offsets);
            *rec_offs_base(offsets) = offs;
            /* Determine offsets to fields */
            do {
                offs = rec_2_get_field_end_info(rec, i);
                if (offs & REC_2BYTE_SQL_NULL_MASK) {
                    offs &= ~REC_2BYTE_SQL_NULL_MASK;
                    offs |= REC_OFFS_SQL_NULL;
                }
                if (offs & REC_2BYTE_EXTERN_MASK) {
                    offs &= ~REC_2BYTE_EXTERN_MASK;
                    offs |= REC_OFFS_EXTERNAL;
                    *rec_offs_base(offsets) |= REC_OFFS_EXTERNAL;
                }
                rec_offs_base(offsets)[ + i] = offs;
            } while (++i < rec_offs_n_fields(offsets));
        }
    }
}