Merge marko@bk-internal.mysql.com:/home/bk/mysql-5.0
into hundin.mysql.fi:/home/marko/mysql-5.0-current
This commit is contained in:
commit
774916a902
@ -316,7 +316,9 @@ btr_cur_search_to_nth_level(
|
||||
if (btr_search_latch.writer == RW_LOCK_NOT_LOCKED
|
||||
&& latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ
|
||||
&& !estimate
|
||||
#ifdef PAGE_CUR_LE_OR_EXTENDS
|
||||
&& mode != PAGE_CUR_LE_OR_EXTENDS
|
||||
#endif /* PAGE_CUR_LE_OR_EXTENDS */
|
||||
&& srv_use_adaptive_hash_indexes
|
||||
&& btr_search_guess_on_hash(index, info, tuple, mode,
|
||||
latch_mode, cursor,
|
||||
@ -391,8 +393,10 @@ btr_cur_search_to_nth_level(
|
||||
break;
|
||||
default:
|
||||
ut_ad(mode == PAGE_CUR_L
|
||||
|| mode == PAGE_CUR_LE
|
||||
|| mode == PAGE_CUR_LE_OR_EXTENDS);
|
||||
#ifdef PAGE_CUR_LE_OR_EXTENDS
|
||||
|| mode == PAGE_CUR_LE_OR_EXTENDS
|
||||
#endif /* PAGE_CUR_LE_OR_EXTENDS */
|
||||
|| mode == PAGE_CUR_LE);
|
||||
page_mode = mode;
|
||||
break;
|
||||
}
|
||||
|
@ -26,11 +26,13 @@ Created 10/4/1994 Heikki Tuuri
|
||||
#define PAGE_CUR_GE 2
|
||||
#define PAGE_CUR_L 3
|
||||
#define PAGE_CUR_LE 4
|
||||
#define PAGE_CUR_LE_OR_EXTENDS 5 /* This is a search mode used in
|
||||
/*#define PAGE_CUR_LE_OR_EXTENDS 5*/ /* This is a search mode used in
|
||||
"column LIKE 'abc%' ORDER BY column DESC";
|
||||
we have to find strings which are <= 'abc' or
|
||||
which extend it */
|
||||
#define PAGE_CUR_DBG 6
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
# define PAGE_CUR_DBG 6 /* As PAGE_CUR_LE, but skips search shortcut */
|
||||
#endif /* UNIV_SEARCH_DEBUG */
|
||||
|
||||
#ifdef PAGE_CUR_ADAPT
|
||||
# ifdef UNIV_SEARCH_PERF_STAT
|
||||
|
@ -47,7 +47,6 @@ page_cur_try_search_shortcut(
|
||||
not yet completely matched */
|
||||
page_cur_t* cursor) /* out: page cursor */
|
||||
{
|
||||
int cmp;
|
||||
rec_t* rec;
|
||||
rec_t* next_rec;
|
||||
ulint low_match;
|
||||
@ -79,9 +78,8 @@ page_cur_try_search_shortcut(
|
||||
up_match = low_match;
|
||||
up_bytes = low_bytes;
|
||||
|
||||
cmp = page_cmp_dtuple_rec_with_match(tuple, rec, offsets, &low_match,
|
||||
&low_bytes);
|
||||
if (cmp == -1) {
|
||||
if (page_cmp_dtuple_rec_with_match(tuple, rec, offsets,
|
||||
&low_match, &low_bytes) < 0) {
|
||||
goto exit_func;
|
||||
}
|
||||
|
||||
@ -89,9 +87,8 @@ page_cur_try_search_shortcut(
|
||||
offsets = rec_get_offsets(next_rec, index, offsets,
|
||||
dtuple_get_n_fields(tuple), &heap);
|
||||
|
||||
cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, offsets,
|
||||
&up_match, &up_bytes);
|
||||
if (cmp != -1) {
|
||||
if (page_cmp_dtuple_rec_with_match(tuple, next_rec, offsets,
|
||||
&up_match, &up_bytes) >= 0) {
|
||||
goto exit_func;
|
||||
}
|
||||
|
||||
@ -115,7 +112,7 @@ page_cur_try_search_shortcut(
|
||||
ut_a(*ilow_matched_fields == low_match);
|
||||
ut_a(*ilow_matched_bytes == low_bytes);
|
||||
#endif
|
||||
if (next_rec != page_get_supremum_rec(page)) {
|
||||
if (!page_rec_is_supremum(next_rec)) {
|
||||
|
||||
*iup_matched_fields = up_match;
|
||||
*iup_matched_bytes = up_bytes;
|
||||
@ -137,6 +134,7 @@ exit_func:
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PAGE_CUR_LE_OR_EXTENDS
|
||||
/********************************************************************
|
||||
Checks if the nth field in a record is a character type field which extends
|
||||
the nth field in tuple, i.e., the field is longer or equal in length and has
|
||||
@ -185,6 +183,7 @@ page_cur_rec_field_extends(
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
#endif /* PAGE_CUR_LE_OR_EXTENDS */
|
||||
|
||||
/********************************************************************
|
||||
Searches the right position for a page cursor. */
|
||||
@ -240,9 +239,14 @@ page_cur_search_with_match(
|
||||
ut_ad(dtuple_validate(tuple));
|
||||
ut_ad(dtuple_check_typed(tuple));
|
||||
ut_ad((mode == PAGE_CUR_L) || (mode == PAGE_CUR_LE)
|
||||
|| (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)
|
||||
|| (mode == PAGE_CUR_LE_OR_EXTENDS) || (mode == PAGE_CUR_DBG));
|
||||
|
||||
#ifdef PAGE_CUR_DBG
|
||||
|| (mode == PAGE_CUR_DBG)
|
||||
#endif /* PAGE_CUR_DBG */
|
||||
#ifdef PAGE_CUR_LE_OR_EXTENDS
|
||||
|| (mode == PAGE_CUR_LE_OR_EXTENDS)
|
||||
#endif /* PAGE_CUR_LE_OR_EXTENDS */
|
||||
|| (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE));
|
||||
|
||||
page_check_dir(page);
|
||||
|
||||
#ifdef PAGE_CUR_ADAPT
|
||||
@ -261,16 +265,18 @@ page_cur_search_with_match(
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*#ifdef UNIV_SEARCH_DEBUG */
|
||||
# ifdef PAGE_CUR_DBG
|
||||
if (mode == PAGE_CUR_DBG) {
|
||||
mode = PAGE_CUR_LE;
|
||||
}
|
||||
/*#endif */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The following flag does not work for non-latin1 char sets because
|
||||
cmp_full_field does not tell how many bytes matched */
|
||||
#ifdef PAGE_CUR_LE_OR_EXTENDS
|
||||
ut_a(mode != PAGE_CUR_LE_OR_EXTENDS);
|
||||
#endif /* PAGE_CUR_LE_OR_EXTENDS */
|
||||
|
||||
/* If mode PAGE_CUR_G is specified, we are trying to position the
|
||||
cursor to answer a query of the form "tuple < X", where tuple is
|
||||
@ -308,33 +314,36 @@ page_cur_search_with_match(
|
||||
cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets,
|
||||
&cur_matched_fields,
|
||||
&cur_matched_bytes);
|
||||
if (cmp == 1) {
|
||||
if (UNIV_LIKELY(cmp > 0)) {
|
||||
low_slot_match:
|
||||
low = mid;
|
||||
low_matched_fields = cur_matched_fields;
|
||||
low_matched_bytes = cur_matched_bytes;
|
||||
|
||||
} else if (cmp == -1) {
|
||||
} else if (UNIV_LIKELY(cmp /* == -1 */)) {
|
||||
#ifdef PAGE_CUR_LE_OR_EXTENDS
|
||||
if (mode == PAGE_CUR_LE_OR_EXTENDS
|
||||
&& page_cur_rec_field_extends(tuple, mid_rec,
|
||||
offsets, cur_matched_fields)) {
|
||||
low = mid;
|
||||
low_matched_fields = cur_matched_fields;
|
||||
low_matched_bytes = cur_matched_bytes;
|
||||
} else {
|
||||
up = mid;
|
||||
up_matched_fields = cur_matched_fields;
|
||||
up_matched_bytes = cur_matched_bytes;
|
||||
}
|
||||
|
||||
} else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
|
||||
|| mode == PAGE_CUR_LE_OR_EXTENDS) {
|
||||
low = mid;
|
||||
low_matched_fields = cur_matched_fields;
|
||||
low_matched_bytes = cur_matched_bytes;
|
||||
} else {
|
||||
goto low_slot_match;
|
||||
}
|
||||
#endif /* PAGE_CUR_LE_OR_EXTENDS */
|
||||
up_slot_match:
|
||||
up = mid;
|
||||
up_matched_fields = cur_matched_fields;
|
||||
up_matched_bytes = cur_matched_bytes;
|
||||
|
||||
} else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
|
||||
#ifdef PAGE_CUR_LE_OR_EXTENDS
|
||||
|| mode == PAGE_CUR_LE_OR_EXTENDS
|
||||
#endif /* PAGE_CUR_LE_OR_EXTENDS */
|
||||
) {
|
||||
|
||||
goto low_slot_match;
|
||||
} else {
|
||||
|
||||
goto up_slot_match;
|
||||
}
|
||||
}
|
||||
|
||||
@ -360,32 +369,35 @@ page_cur_search_with_match(
|
||||
cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets,
|
||||
&cur_matched_fields,
|
||||
&cur_matched_bytes);
|
||||
if (cmp == 1) {
|
||||
if (UNIV_LIKELY(cmp > 0)) {
|
||||
low_rec_match:
|
||||
low_rec = mid_rec;
|
||||
low_matched_fields = cur_matched_fields;
|
||||
low_matched_bytes = cur_matched_bytes;
|
||||
|
||||
} else if (cmp == -1) {
|
||||
} else if (UNIV_LIKELY(cmp /* == -1 */)) {
|
||||
#ifdef PAGE_CUR_LE_OR_EXTENDS
|
||||
if (mode == PAGE_CUR_LE_OR_EXTENDS
|
||||
&& page_cur_rec_field_extends(tuple, mid_rec,
|
||||
offsets, cur_matched_fields)) {
|
||||
low_rec = mid_rec;
|
||||
low_matched_fields = cur_matched_fields;
|
||||
low_matched_bytes = cur_matched_bytes;
|
||||
} else {
|
||||
up_rec = mid_rec;
|
||||
up_matched_fields = cur_matched_fields;
|
||||
up_matched_bytes = cur_matched_bytes;
|
||||
|
||||
goto low_rec_match;
|
||||
}
|
||||
} else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
|
||||
|| mode == PAGE_CUR_LE_OR_EXTENDS) {
|
||||
low_rec = mid_rec;
|
||||
low_matched_fields = cur_matched_fields;
|
||||
low_matched_bytes = cur_matched_bytes;
|
||||
} else {
|
||||
#endif /* PAGE_CUR_LE_OR_EXTENDS */
|
||||
up_rec_match:
|
||||
up_rec = mid_rec;
|
||||
up_matched_fields = cur_matched_fields;
|
||||
up_matched_bytes = cur_matched_bytes;
|
||||
} else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
|
||||
#ifdef PAGE_CUR_LE_OR_EXTENDS
|
||||
|| mode == PAGE_CUR_LE_OR_EXTENDS
|
||||
#endif /* PAGE_CUR_LE_OR_EXTENDS */
|
||||
) {
|
||||
|
||||
goto low_rec_match;
|
||||
} else {
|
||||
|
||||
goto up_rec_match;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,30 +601,38 @@ rec_set_nth_field_extern_bit_new(
|
||||
|
||||
/* read the lengths of fields 0..n */
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
ibool is_null;
|
||||
ulint len;
|
||||
field = dict_index_get_nth_field(index, i);
|
||||
type = dict_col_get_type(dict_field_get_col(field));
|
||||
is_null = !(dtype_get_prtype(type) & DATA_NOT_NULL);
|
||||
if (is_null) {
|
||||
/* nullable field => read the null flag */
|
||||
is_null = !!(*nulls & null_mask);
|
||||
if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
|
||||
if (UNIV_UNLIKELY(!(byte) null_mask)) {
|
||||
nulls--;
|
||||
null_mask = 1;
|
||||
}
|
||||
|
||||
if (*nulls & null_mask) {
|
||||
null_mask <<= 1;
|
||||
/* NULL fields cannot be external. */
|
||||
ut_ad(i != ith);
|
||||
continue;
|
||||
}
|
||||
|
||||
null_mask <<= 1;
|
||||
if (null_mask == 0x100)
|
||||
nulls--, null_mask = 1;
|
||||
}
|
||||
if (is_null || field->fixed_len) {
|
||||
/* No length (or extern bit) is stored for
|
||||
fields that are NULL or fixed-length. */
|
||||
if (field->fixed_len) {
|
||||
/* fixed-length fields cannot be external
|
||||
(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);
|
||||
continue;
|
||||
}
|
||||
len = *lens--;
|
||||
lens--;
|
||||
if (dtype_get_len(type) > 255
|
||||
|| dtype_get_mtype(type) == DATA_BLOB) {
|
||||
ulint len = lens[1];
|
||||
if (len & 0x80) { /* 1exxxxxx: 2-byte length */
|
||||
if (i == ith) {
|
||||
if (!val == !(len & 0x20)) {
|
||||
if (!val == !(len & 0x40)) {
|
||||
return; /* no change */
|
||||
}
|
||||
/* toggle the extern bit */
|
||||
@ -823,6 +831,7 @@ rec_convert_dtuple_to_rec_new(
|
||||
byte* lens;
|
||||
ulint len;
|
||||
ulint i;
|
||||
ulint n_node_ptr_field;
|
||||
ulint fixed_len;
|
||||
ulint null_mask = 1;
|
||||
const ulint n_fields = dtuple_get_n_fields(dtuple);
|
||||
@ -831,16 +840,26 @@ rec_convert_dtuple_to_rec_new(
|
||||
ut_ad(index->table->comp);
|
||||
|
||||
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:
|
||||
ut_ad(n_fields <= dict_index_get_n_fields(index));
|
||||
n_node_ptr_field = ULINT_UNDEFINED;
|
||||
break;
|
||||
case REC_STATUS_NODE_PTR:
|
||||
ut_ad(n_fields == dict_index_get_n_unique_in_tree(index) + 1);
|
||||
n_node_ptr_field = n_fields - 1;
|
||||
break;
|
||||
case REC_STATUS_INFIMUM:
|
||||
case REC_STATUS_SUPREMUM:
|
||||
ut_ad(n_fields == 1);
|
||||
n_node_ptr_field = ULINT_UNDEFINED;
|
||||
goto init;
|
||||
default:
|
||||
ut_a(0);
|
||||
@ -852,15 +871,18 @@ rec_convert_dtuple_to_rec_new(
|
||||
rec += (index->n_nullable + 7) / 8;
|
||||
|
||||
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);
|
||||
type = dfield_get_type(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;
|
||||
|
||||
if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
|
||||
@ -902,27 +924,33 @@ init:
|
||||
type = dfield_get_type(field);
|
||||
len = dfield_get_len(field);
|
||||
|
||||
if (status == REC_STATUS_NODE_PTR && i == n_fields - 1) {
|
||||
fixed_len = 4;
|
||||
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
|
||||
ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
|
||||
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;
|
||||
|
||||
if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
|
||||
/* nullable field */
|
||||
ut_ad(index->n_nullable > 0);
|
||||
|
||||
if (UNIV_UNLIKELY(!(byte) null_mask)) {
|
||||
nulls--;
|
||||
null_mask = 1;
|
||||
}
|
||||
|
||||
ut_ad(*nulls < null_mask);
|
||||
|
||||
/* set the null flag if necessary */
|
||||
if (len == UNIV_SQL_NULL) {
|
||||
*nulls |= null_mask;
|
||||
}
|
||||
null_mask <<= 1;
|
||||
if (null_mask == 0x100)
|
||||
nulls--, null_mask = 1;
|
||||
if (len == UNIV_SQL_NULL)
|
||||
null_mask <<= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
null_mask <<= 1;
|
||||
}
|
||||
/* only nullable fields can be null */
|
||||
ut_ad(len != UNIV_SQL_NULL);
|
||||
@ -942,7 +970,7 @@ init:
|
||||
*lens-- = (byte) len;
|
||||
}
|
||||
}
|
||||
copy:
|
||||
|
||||
memcpy(end, dfield_get_data(field), len);
|
||||
end += len;
|
||||
}
|
||||
@ -1105,7 +1133,6 @@ rec_copy_prefix_to_buf(
|
||||
dtype_t* type;
|
||||
ulint i;
|
||||
ulint prefix_len;
|
||||
ibool is_null;
|
||||
ulint null_mask;
|
||||
ulint status;
|
||||
|
||||
@ -1146,20 +1173,22 @@ rec_copy_prefix_to_buf(
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
field = dict_index_get_nth_field(index, i);
|
||||
type = dict_col_get_type(dict_field_get_col(field));
|
||||
is_null = !(dtype_get_prtype(type) & DATA_NOT_NULL);
|
||||
if (is_null) {
|
||||
if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
|
||||
/* nullable field => read the null flag */
|
||||
is_null = !!(*nulls & null_mask);
|
||||
null_mask <<= 1;
|
||||
if (null_mask == 0x100) {
|
||||
--nulls;
|
||||
UNIV_PREFETCH_R(nulls);
|
||||
if (UNIV_UNLIKELY(!(byte) null_mask)) {
|
||||
nulls--;
|
||||
null_mask = 1;
|
||||
}
|
||||
|
||||
if (*nulls & null_mask) {
|
||||
null_mask <<= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
null_mask <<= 1;
|
||||
}
|
||||
|
||||
if (is_null) {
|
||||
} else if (field->fixed_len) {
|
||||
if (field->fixed_len) {
|
||||
prefix_len += field->fixed_len;
|
||||
} else {
|
||||
ulint len = *lens--;
|
||||
|
@ -2955,21 +2955,44 @@ build_template(
|
||||
templ = prebuilt->mysql_template + n_requested_fields;
|
||||
field = table->field[i];
|
||||
|
||||
ibool index_contains_field=
|
||||
dict_index_contains_col_or_prefix(index, i);
|
||||
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
|
||||
/* Decide which columns we should fetch
|
||||
and which we can skip. */
|
||||
register const ibool index_contains_field =
|
||||
dict_index_contains_col_or_prefix(index, i);
|
||||
|
||||
if (templ_type == ROW_MYSQL_REC_FIELDS &&
|
||||
((prebuilt->read_just_key && !index_contains_field) ||
|
||||
(!(fetch_all_in_key && index_contains_field) &&
|
||||
!(fetch_primary_key_cols &&
|
||||
dict_table_col_in_clustered_key(index->table, i)) &&
|
||||
thd->query_id != field->query_id))) {
|
||||
if (!index_contains_field && prebuilt->read_just_key) {
|
||||
/* If this is a 'key read', we do not need
|
||||
columns that are not in the key */
|
||||
|
||||
goto skip_field;
|
||||
}
|
||||
|
||||
if (index_contains_field && fetch_all_in_key) {
|
||||
/* This field is needed in the query */
|
||||
|
||||
goto include_field;
|
||||
}
|
||||
|
||||
if (thd->query_id == field->query_id) {
|
||||
/* This field is needed in the query */
|
||||
|
||||
goto include_field;
|
||||
}
|
||||
|
||||
if (fetch_primary_key_cols
|
||||
&& dict_table_col_in_clustered_key(index->table,
|
||||
i)) {
|
||||
/* This field is needed in the query */
|
||||
|
||||
goto include_field;
|
||||
}
|
||||
|
||||
/* This field is not needed in the query, skip it */
|
||||
|
||||
goto skip_field;
|
||||
}
|
||||
|
||||
include_field:
|
||||
n_requested_fields++;
|
||||
|
||||
templ->col_no = i;
|
||||
|
Loading…
x
Reference in New Issue
Block a user