Commit 85036af7 authored by unknown's avatar unknown

InnoDB: Fix a bug in BLOB handling; optimize null flag handling.


innobase/rem/rem0rec.c:
  rec_set_nth_field_extern_bit_new(): Fix a bug
  (read the "extern" flag from the correct position).
  
  rec_set_nth_field_extern_bit_new(),
  rec_convert_dtuple_to_rec_new(),
  rec_copy_prefix_to_buf(): Eliminate variables, reduce branching,
  optimize the handling of the null flags.
parent 384a0c0a
...@@ -601,30 +601,38 @@ rec_set_nth_field_extern_bit_new( ...@@ -601,30 +601,38 @@ rec_set_nth_field_extern_bit_new(
/* read the lengths of fields 0..n */ /* read the lengths of fields 0..n */
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
ibool is_null;
ulint len;
field = dict_index_get_nth_field(index, i); field = dict_index_get_nth_field(index, i);
type = dict_col_get_type(dict_field_get_col(field)); type = dict_col_get_type(dict_field_get_col(field));
is_null = !(dtype_get_prtype(type) & DATA_NOT_NULL); if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
if (is_null) { if (UNIV_UNLIKELY(!(byte) null_mask)) {
/* nullable field => read the null flag */ nulls--;
is_null = !!(*nulls & null_mask); null_mask = 1;
}
if (*nulls & null_mask) {
null_mask <<= 1;
/* NULL fields cannot be external. */
ut_ad(i != ith);
continue;
}
null_mask <<= 1; null_mask <<= 1;
if (null_mask == 0x100)
nulls--, null_mask = 1;
} }
if (is_null || field->fixed_len) { if (field->fixed_len) {
/* No length (or extern bit) is stored for /* fixed-length fields cannot be external
fields that are NULL or fixed-length. */ (Fixed-length fields longer than
DICT_MAX_COL_PREFIX_LEN will be treated as
variable-length ones in dict_index_add_col().) */
ut_ad(i != ith); ut_ad(i != ith);
continue; continue;
} }
len = *lens--; lens--;
if (dtype_get_len(type) > 255 if (dtype_get_len(type) > 255
|| dtype_get_mtype(type) == DATA_BLOB) { || dtype_get_mtype(type) == DATA_BLOB) {
ulint len = lens[1];
if (len & 0x80) { /* 1exxxxxx: 2-byte length */ if (len & 0x80) { /* 1exxxxxx: 2-byte length */
if (i == ith) { if (i == ith) {
if (!val == !(len & 0x20)) { if (!val == !(len & 0x40)) {
return; /* no change */ return; /* no change */
} }
/* toggle the extern bit */ /* toggle the extern bit */
...@@ -823,6 +831,7 @@ rec_convert_dtuple_to_rec_new( ...@@ -823,6 +831,7 @@ rec_convert_dtuple_to_rec_new(
byte* lens; byte* lens;
ulint len; ulint len;
ulint i; ulint i;
ulint n_node_ptr_field;
ulint fixed_len; ulint fixed_len;
ulint null_mask = 1; ulint null_mask = 1;
const ulint n_fields = dtuple_get_n_fields(dtuple); const ulint n_fields = dtuple_get_n_fields(dtuple);
...@@ -831,16 +840,26 @@ rec_convert_dtuple_to_rec_new( ...@@ -831,16 +840,26 @@ rec_convert_dtuple_to_rec_new(
ut_ad(index->table->comp); ut_ad(index->table->comp);
ut_ad(n_fields > 0); ut_ad(n_fields > 0);
switch (status) {
/* Try to ensure that the memset() between the for() loops
completes fast. The address is not exact, but UNIV_PREFETCH
should never generate a memory fault. */
UNIV_PREFETCH_RW(rec - REC_N_NEW_EXTRA_BYTES - n_fields);
UNIV_PREFETCH_RW(rec);
switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
case REC_STATUS_ORDINARY: case REC_STATUS_ORDINARY:
ut_ad(n_fields <= dict_index_get_n_fields(index)); ut_ad(n_fields <= dict_index_get_n_fields(index));
n_node_ptr_field = ULINT_UNDEFINED;
break; break;
case REC_STATUS_NODE_PTR: case REC_STATUS_NODE_PTR:
ut_ad(n_fields == dict_index_get_n_unique_in_tree(index) + 1); ut_ad(n_fields == dict_index_get_n_unique_in_tree(index) + 1);
n_node_ptr_field = n_fields - 1;
break; break;
case REC_STATUS_INFIMUM: case REC_STATUS_INFIMUM:
case REC_STATUS_SUPREMUM: case REC_STATUS_SUPREMUM:
ut_ad(n_fields == 1); ut_ad(n_fields == 1);
n_node_ptr_field = ULINT_UNDEFINED;
goto init; goto init;
default: default:
ut_a(0); ut_a(0);
...@@ -852,15 +871,18 @@ rec_convert_dtuple_to_rec_new( ...@@ -852,15 +871,18 @@ rec_convert_dtuple_to_rec_new(
rec += (index->n_nullable + 7) / 8; rec += (index->n_nullable + 7) / 8;
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
#ifdef UNIV_DEBUG
field = dtuple_get_nth_field(dtuple, i);
type = dfield_get_type(field);
ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
ut_ad(dfield_get_len(field) == 4);
#endif /* UNIV_DEBUG */
goto init;
}
field = dtuple_get_nth_field(dtuple, i); field = dtuple_get_nth_field(dtuple, i);
type = dfield_get_type(field); type = dfield_get_type(field);
len = dfield_get_len(field); len = dfield_get_len(field);
if (status == REC_STATUS_NODE_PTR && i == n_fields - 1) {
fixed_len = 4;
ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
ut_ad(len == 4);
continue;
}
fixed_len = dict_index_get_nth_field(index, i)->fixed_len; fixed_len = dict_index_get_nth_field(index, i)->fixed_len;
if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) { if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
...@@ -902,27 +924,33 @@ rec_convert_dtuple_to_rec_new( ...@@ -902,27 +924,33 @@ rec_convert_dtuple_to_rec_new(
type = dfield_get_type(field); type = dfield_get_type(field);
len = dfield_get_len(field); len = dfield_get_len(field);
if (status == REC_STATUS_NODE_PTR && i == n_fields - 1) { if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
fixed_len = 4;
ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL); ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
ut_ad(len == 4); ut_ad(len == 4);
goto copy; memcpy(end, dfield_get_data(field), len);
break;
} }
fixed_len = dict_index_get_nth_field(index, i)->fixed_len; fixed_len = dict_index_get_nth_field(index, i)->fixed_len;
if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) { if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
/* nullable field */ /* nullable field */
ut_ad(index->n_nullable > 0); ut_ad(index->n_nullable > 0);
if (UNIV_UNLIKELY(!(byte) null_mask)) {
nulls--;
null_mask = 1;
}
ut_ad(*nulls < null_mask); ut_ad(*nulls < null_mask);
/* set the null flag if necessary */ /* set the null flag if necessary */
if (len == UNIV_SQL_NULL) { if (len == UNIV_SQL_NULL) {
*nulls |= null_mask; *nulls |= null_mask;
null_mask <<= 1;
continue;
} }
null_mask <<= 1; null_mask <<= 1;
if (null_mask == 0x100)
nulls--, null_mask = 1;
if (len == UNIV_SQL_NULL)
continue;
} }
/* only nullable fields can be null */ /* only nullable fields can be null */
ut_ad(len != UNIV_SQL_NULL); ut_ad(len != UNIV_SQL_NULL);
...@@ -942,7 +970,7 @@ rec_convert_dtuple_to_rec_new( ...@@ -942,7 +970,7 @@ rec_convert_dtuple_to_rec_new(
*lens-- = (byte) len; *lens-- = (byte) len;
} }
} }
copy:
memcpy(end, dfield_get_data(field), len); memcpy(end, dfield_get_data(field), len);
end += len; end += len;
} }
...@@ -1105,7 +1133,6 @@ rec_copy_prefix_to_buf( ...@@ -1105,7 +1133,6 @@ rec_copy_prefix_to_buf(
dtype_t* type; dtype_t* type;
ulint i; ulint i;
ulint prefix_len; ulint prefix_len;
ibool is_null;
ulint null_mask; ulint null_mask;
ulint status; ulint status;
...@@ -1146,20 +1173,22 @@ rec_copy_prefix_to_buf( ...@@ -1146,20 +1173,22 @@ rec_copy_prefix_to_buf(
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
field = dict_index_get_nth_field(index, i); field = dict_index_get_nth_field(index, i);
type = dict_col_get_type(dict_field_get_col(field)); type = dict_col_get_type(dict_field_get_col(field));
is_null = !(dtype_get_prtype(type) & DATA_NOT_NULL); if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
if (is_null) {
/* nullable field => read the null flag */ /* nullable field => read the null flag */
is_null = !!(*nulls & null_mask); if (UNIV_UNLIKELY(!(byte) null_mask)) {
null_mask <<= 1; nulls--;
if (null_mask == 0x100) {
--nulls;
UNIV_PREFETCH_R(nulls);
null_mask = 1; null_mask = 1;
} }
if (*nulls & null_mask) {
null_mask <<= 1;
continue;
}
null_mask <<= 1;
} }
if (is_null) { if (field->fixed_len) {
} else if (field->fixed_len) {
prefix_len += field->fixed_len; prefix_len += field->fixed_len;
} else { } else {
ulint len = *lens--; ulint len = *lens--;
......
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