Commit 2a77ce27 authored by marko's avatar marko

branches/zip: Refactor some code for handling records in ROW_FORMAT=COMPACT.

rec_get_converted_size_new(): Rename to rec_get_converted_size_comp().
Add const qualifier to dtuple.  Remove the assertion
dict_table_is_comp(index->table), because this function will be invoked
when populating the temporary files in fast index creation.

rec_convert_dtuple_to_rec_new(): Rename to rec_convert_dtuple_to_rec_comp().
Add parameter "extra".

rec_init_offsets_comp_ordinary(): New function.  Used in rec_init_offsets().
parent ac6fb591
...@@ -335,6 +335,22 @@ rec_get_offsets_func( ...@@ -335,6 +335,22 @@ rec_get_offsets_func(
#define rec_get_offsets(rec,index,offsets,n,heap) \ #define rec_get_offsets(rec,index,offsets,n,heap) \
rec_get_offsets_func(rec,index,offsets,n,heap,__FILE__,__LINE__) rec_get_offsets_func(rec,index,offsets,n,heap,__FILE__,__LINE__)
/**********************************************************
Determine the offset to each field in a leaf-page record
in ROW_FORMAT=COMPACT. This is a special case of
rec_init_offsets() and rec_get_offsets_func(). */
void
rec_init_offsets_comp_ordinary(
/*===========================*/
const rec_t* rec, /* in: physical record in ROW_FORMAT=COMPACT */
ulint extra, /* in: number of bytes to reserve between
the record header and the data payload
(usually REC_N_NEW_EXTRA_BYTES) */
dict_index_t* index, /* in: record descriptor */
ulint* offsets);/* in/out: array of offsets;
in: n=rec_offs_n_fields(offsets) */
/********************************************************** /**********************************************************
The following function determines the offsets to each field The following function determines the offsets to each field
in the record. It can reuse a previously allocated array. */ in the record. It can reuse a previously allocated array. */
...@@ -589,6 +605,22 @@ rec_fold( ...@@ -589,6 +605,22 @@ rec_fold(
dulint tree_id) /* in: index tree id */ dulint tree_id) /* in: index tree id */
__attribute__((pure)); __attribute__((pure));
/************************************************************* /*************************************************************
Builds a ROW_FORMAT=COMPACT record out of a data tuple. */
byte*
rec_convert_dtuple_to_rec_comp(
/*===========================*/
/* out: pointer to the start of data payload */
byte* buf, /* in: start address of the data area */
ulint extra, /* in: number of bytes to reserve between
the record header and the data payload
(usually REC_N_NEW_EXTRA_BYTES) */
dict_index_t* index, /* in: record descriptor */
const dtuple_t* dtuple, /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers,
in ascending order */
ulint n_ext); /* in: number of elements in ext */
/*************************************************************
Builds a physical record out of a data tuple and Builds a physical record out of a data tuple and
stores it into the given buffer. */ stores it into the given buffer. */
...@@ -617,6 +649,18 @@ rec_get_converted_extra_size( ...@@ -617,6 +649,18 @@ rec_get_converted_extra_size(
ulint n_ext) /* in: number of externally stored columns */ ulint n_ext) /* in: number of externally stored columns */
__attribute__((const)); __attribute__((const));
/************************************************************** /**************************************************************
Determines the size of a data tuple in ROW_FORMAT=COMPACT. */
ulint
rec_get_converted_size_comp(
/*========================*/
/* out: size */
dict_index_t* index, /* in: record descriptor;
dict_table_is_comp() is assumed to hold */
const dtuple_t* dtuple, /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers */
ulint n_ext); /* in: number of elements in ext */
/**************************************************************
The following function returns the size of a data tuple when converted to The following function returns the size of a data tuple when converted to
a physical record. */ a physical record. */
UNIV_INLINE UNIV_INLINE
......
...@@ -1510,18 +1510,6 @@ rec_get_converted_extra_size( ...@@ -1510,18 +1510,6 @@ rec_get_converted_extra_size(
return(REC_N_OLD_EXTRA_BYTES + 2 * n_fields); return(REC_N_OLD_EXTRA_BYTES + 2 * n_fields);
} }
/**************************************************************
The following function returns the size of a data tuple when converted to
a new-style physical record. */
ulint
rec_get_converted_size_new(
/*=======================*/
/* out: size */
dict_index_t* index, /* in: record descriptor */
const dtuple_t* dtuple, /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers */
ulint n_ext); /* in: number of elements in ext */
/************************************************************** /**************************************************************
The following function returns the size of a data tuple when converted to The following function returns the size of a data tuple when converted to
a physical record. */ a physical record. */
...@@ -1550,7 +1538,7 @@ rec_get_converted_size( ...@@ -1550,7 +1538,7 @@ rec_get_converted_size(
: dict_index_get_n_fields(index))); : dict_index_get_n_fields(index)));
if (dict_table_is_comp(index->table)) { if (dict_table_is_comp(index->table)) {
return(rec_get_converted_size_new(index, dtuple, ext, n_ext)); return(rec_get_converted_size_comp(index, dtuple, ext, n_ext));
} }
data_size = dtuple_get_data_size(dtuple); data_size = dtuple_get_data_size(dtuple);
......
...@@ -211,6 +211,97 @@ rec_get_n_extern_new( ...@@ -211,6 +211,97 @@ rec_get_n_extern_new(
return(n_extern); return(n_extern);
} }
/**********************************************************
Determine the offset to each field in a leaf-page record
in ROW_FORMAT=COMPACT. This is a special case of
rec_init_offsets() and rec_get_offsets_func(). */
void
rec_init_offsets_comp_ordinary(
/*===========================*/
const rec_t* rec, /* in: physical record in ROW_FORMAT=COMPACT */
ulint extra, /* in: number of bytes to reserve between
the record header and the data payload
(usually REC_N_NEW_EXTRA_BYTES) */
dict_index_t* index, /* in: record descriptor */
ulint* offsets)/* in/out: array of offsets;
in: n=rec_offs_n_fields(offsets) */
{
ulint i = 0;
ulint offs = 0;
ulint any_ext = 0;
const byte* nulls = rec - (extra + 1);
const byte* lens = nulls - (index->n_nullable + 7) / 8;;
dict_field_t* field;
ulint null_mask = 1;
/* read the lengths of fields 0..n */
do {
ulint len;
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 = 1;
}
if (*nulls & null_mask) {
null_mask <<= 1;
/* 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 <<= 1;
}
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 (UNIV_UNLIKELY(col->len > 255)
|| UNIV_UNLIKELY(col->mtype
== DATA_BLOB)) {
if (len & 0x80) {
/* 1exxxxxxx xxxxxxxx */
len <<= 8;
len |= *lens--;
offs += len & 0x3fff;
if (UNIV_UNLIKELY(len
& 0x4000)) {
ut_ad(dict_index_is_clust
(index));
any_ext = REC_OFFS_EXTERNAL;
len = offs
| REC_OFFS_EXTERNAL;
} else {
len = offs;
}
goto resolved;
}
}
len = offs += len;
} else {
len = offs += field->fixed_len;
}
resolved:
rec_offs_base(offsets)[i + 1] = len;
} while (++i < rec_offs_n_fields(offsets));
*rec_offs_base(offsets)
= (rec - (lens + 1)) | REC_OFFS_COMPACT | any_ext;
}
/********************************************************** /**********************************************************
The following function determines the offsets to each field in the The following function determines the offsets to each field in the
record. The offsets are written to a previously allocated array of record. The offsets are written to a previously allocated array of
...@@ -240,7 +331,6 @@ rec_init_offsets( ...@@ -240,7 +331,6 @@ rec_init_offsets(
rec_offs_make_valid(rec, index, offsets); rec_offs_make_valid(rec, index, offsets);
if (dict_table_is_comp(index->table)) { if (dict_table_is_comp(index->table)) {
ulint any_ext;
const byte* nulls; const byte* nulls;
const byte* lens; const byte* lens;
dict_field_t* field; dict_field_t* field;
...@@ -261,13 +351,15 @@ rec_init_offsets( ...@@ -261,13 +351,15 @@ rec_init_offsets(
= dict_index_get_n_unique_in_tree(index); = dict_index_get_n_unique_in_tree(index);
break; break;
case REC_STATUS_ORDINARY: case REC_STATUS_ORDINARY:
break; rec_init_offsets_comp_ordinary(rec,
REC_N_NEW_EXTRA_BYTES,
index, offsets);
return;
} }
nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
lens = nulls - (index->n_nullable + 7) / 8; lens = nulls - (index->n_nullable + 7) / 8;
offs = 0; offs = 0;
any_ext = 0;
null_mask = 1; null_mask = 1;
/* read the lengths of fields 0..n */ /* read the lengths of fields 0..n */
...@@ -313,17 +405,9 @@ rec_init_offsets( ...@@ -313,17 +405,9 @@ rec_init_offsets(
len <<= 8; len <<= 8;
len |= *lens--; len |= *lens--;
offs += len & 0x3fff; ut_a(len <= 0x3fff);
if (UNIV_UNLIKELY(len offs += len;
& 0x4000)) {
ut_ad(dict_index_is_clust
(index));
any_ext = REC_OFFS_EXTERNAL;
len = offs
| REC_OFFS_EXTERNAL;
} else {
len = offs; len = offs;
}
goto resolved; goto resolved;
} }
...@@ -338,7 +422,7 @@ rec_init_offsets( ...@@ -338,7 +422,7 @@ rec_init_offsets(
} while (++i < rec_offs_n_fields(offsets)); } while (++i < rec_offs_n_fields(offsets));
*rec_offs_base(offsets) *rec_offs_base(offsets)
= (rec - (lens + 1)) | REC_OFFS_COMPACT | any_ext; = (rec - (lens + 1)) | REC_OFFS_COMPACT;
} else { } else {
/* Old-style record: determine extra size and end offsets */ /* Old-style record: determine extra size and end offsets */
offs = REC_N_OLD_EXTRA_BYTES; offs = REC_N_OLD_EXTRA_BYTES;
...@@ -623,15 +707,15 @@ rec_get_nth_field_offs_old( ...@@ -623,15 +707,15 @@ rec_get_nth_field_offs_old(
} }
/************************************************************** /**************************************************************
The following function returns the size of a data tuple when converted to Determines the size of a data tuple in ROW_FORMAT=COMPACT. */
a new-style physical record. */
ulint ulint
rec_get_converted_size_new( rec_get_converted_size_comp(
/*=======================*/ /*========================*/
/* out: size */ /* out: size */
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor;
const dtuple_t* dtuple, dict_table_is_comp() is assumed to hold */
const dtuple_t* dtuple, /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers */ const ulint* ext, /* in: array of extern field numbers */
ulint n_ext) /* in: number of elements in ext */ ulint n_ext) /* in: number of elements in ext */
{ {
...@@ -641,7 +725,7 @@ rec_get_converted_size_new( ...@@ -641,7 +725,7 @@ rec_get_converted_size_new(
ulint j; ulint j;
ulint n_fields; ulint n_fields;
ut_ad(index && dtuple); ut_ad(index && dtuple);
ut_ad(dict_table_is_comp(index->table)); ut_ad(dtuple_validate(dtuple));
switch (dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK) { switch (dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK) {
case REC_STATUS_ORDINARY: case REC_STATUS_ORDINARY:
...@@ -883,15 +967,16 @@ rec_convert_dtuple_to_rec_old( ...@@ -883,15 +967,16 @@ rec_convert_dtuple_to_rec_old(
} }
/************************************************************* /*************************************************************
Builds a new-style physical record out of a data tuple and Builds a ROW_FORMAT=COMPACT record out of a data tuple. */
stores it beginning from the start of the given buffer. */
static byte*
rec_t* rec_convert_dtuple_to_rec_comp(
rec_convert_dtuple_to_rec_new( /*===========================*/
/*==========================*/ /* out: pointer to the start of data payload */
/* out: pointer to the origin byte* buf, /* in: start address of the data area */
of physical record */ ulint extra, /* in: number of bytes to reserve between
byte* buf, /* in: start address of the physical record */ the record header and the data payload
(usually REC_N_NEW_EXTRA_BYTES) */
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor */
const dtuple_t* dtuple, /* in: data tuple */ const dtuple_t* dtuple, /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers, const ulint* ext, /* in: array of extern field numbers,
...@@ -900,7 +985,7 @@ rec_convert_dtuple_to_rec_new( ...@@ -900,7 +985,7 @@ rec_convert_dtuple_to_rec_new(
{ {
const dfield_t* field; const dfield_t* field;
const dtype_t* type; const dtype_t* type;
rec_t* rec = buf + REC_N_NEW_EXTRA_BYTES; rec_t* rec = buf + extra;
byte* end; byte* end;
byte* nulls; byte* nulls;
byte* lens; byte* lens;
...@@ -917,7 +1002,7 @@ rec_convert_dtuple_to_rec_new( ...@@ -917,7 +1002,7 @@ rec_convert_dtuple_to_rec_new(
/* Try to ensure that the memset() between the for() loops /* Try to ensure that the memset() between the for() loops
completes fast. The address is not exact, but UNIV_PREFETCH completes fast. The address is not exact, but UNIV_PREFETCH
should never generate a memory fault. */ should never generate a memory fault. */
UNIV_PREFETCH_RW(rec - REC_N_NEW_EXTRA_BYTES - n_fields); UNIV_PREFETCH_RW(buf - n_fields);
UNIV_PREFETCH_RW(rec); UNIV_PREFETCH_RW(rec);
switch (UNIV_EXPECT(dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK, switch (UNIV_EXPECT(dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK,
...@@ -986,13 +1071,10 @@ rec_convert_dtuple_to_rec_new( ...@@ -986,13 +1071,10 @@ rec_convert_dtuple_to_rec_new(
init: init:
ut_ad(j == n_ext); ut_ad(j == n_ext);
end = rec; end = rec;
nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); nulls = rec - (extra + 1);
lens = nulls - (index->n_nullable + 7) / 8; lens = nulls - (index->n_nullable + 7) / 8;
/* clear the SQL-null flags */ /* clear the SQL-null flags */
memset (lens + 1, 0, nulls - lens); memset(lens + 1, 0, nulls - lens);
/* Set the info bits of the record */
rec_set_info_and_status_bits(rec, dtuple_get_info_bits(dtuple));
/* Store the data and the offsets */ /* Store the data and the offsets */
...@@ -1063,6 +1145,31 @@ rec_convert_dtuple_to_rec_new( ...@@ -1063,6 +1145,31 @@ rec_convert_dtuple_to_rec_new(
return(rec); return(rec);
} }
/*************************************************************
Builds a new-style physical record out of a data tuple and
stores it beginning from the start of the given buffer. */
static
rec_t*
rec_convert_dtuple_to_rec_new(
/*==========================*/
/* out: pointer to the origin
of physical record */
byte* buf, /* in: start address of the physical record */
dict_index_t* index, /* in: record descriptor */
const dtuple_t* dtuple, /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers,
in ascending order */
ulint n_ext) /* in: number of elements in ext */
{
rec_t* rec = rec_convert_dtuple_to_rec_comp(
buf, REC_N_NEW_EXTRA_BYTES, index, dtuple, ext, n_ext);
/* Set the info bits of the record */
rec_set_info_and_status_bits(rec, dtuple_get_info_bits(dtuple));
return(rec);
}
/************************************************************* /*************************************************************
Builds a physical record out of a data tuple and Builds a physical record out of a data tuple and
stores it beginning from the start of the given buffer. */ stores it beginning from the start of the given buffer. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment