mirror of
https://github.com/MariaDB/server.git
synced 2026-05-11 17:40:11 +02:00
Merge branch '10.1' into 10.2
This commit is contained in:
commit
82aeb6b596
47 changed files with 1566 additions and 295 deletions
|
|
@ -275,7 +275,20 @@ buf_dump(
|
|||
buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) to %s",
|
||||
full_filename);
|
||||
|
||||
f = fopen(tmp_filename, "w");
|
||||
#if defined(__GLIBC__) || defined(__WIN__) || O_CLOEXEC == 0
|
||||
f = fopen(tmp_filename, "w" STR_O_CLOEXEC);
|
||||
#else
|
||||
{
|
||||
int fd;
|
||||
fd = open(tmp_filename, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, 0640);
|
||||
if (fd >= 0) {
|
||||
f = fdopen(fd, "w");
|
||||
}
|
||||
else {
|
||||
f = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (f == NULL) {
|
||||
buf_dump_status(STATUS_ERR,
|
||||
"Cannot open '%s' for writing: %s",
|
||||
|
|
|
|||
|
|
@ -2255,7 +2255,7 @@ AIO::is_linux_native_aio_supported()
|
|||
|
||||
strcpy(name + dirnamelen, "ib_logfile0");
|
||||
|
||||
fd = open(name, O_RDONLY);
|
||||
fd = open(name, O_RDONLY | O_CLOEXEC);
|
||||
|
||||
if (fd == -1) {
|
||||
|
||||
|
|
|
|||
|
|
@ -2915,7 +2915,9 @@ row_sel_field_store_in_mysql_format_func(
|
|||
|| !(templ->mysql_col_len % templ->mbmaxlen));
|
||||
ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len
|
||||
|| (field_no == templ->icp_rec_field_no
|
||||
&& field->prefix_len > 0));
|
||||
&& field->prefix_len > 0)
|
||||
|| templ->rec_field_is_prefix);
|
||||
|
||||
ut_ad(templ->is_virtual
|
||||
|| !(field->prefix_len % templ->mbmaxlen));
|
||||
|
||||
|
|
@ -4061,6 +4063,118 @@ row_sel_fill_vrow(
|
|||
}
|
||||
}
|
||||
|
||||
/** Return the record field length in characters.
|
||||
@param[in] col table column of the field
|
||||
@param[in] field_no field number
|
||||
@param[in] rec physical record
|
||||
@param[in] offsets field offsets in the physical record
|
||||
@return field length in characters. */
|
||||
static
|
||||
size_t
|
||||
rec_field_len_in_chars(
|
||||
const dict_col_t* col,
|
||||
const ulint field_no,
|
||||
const rec_t* rec,
|
||||
const ulint* offsets)
|
||||
{
|
||||
const ulint cset = dtype_get_charset_coll(col->prtype);
|
||||
const CHARSET_INFO* cs = all_charsets[cset];
|
||||
ulint rec_field_len;
|
||||
const char* rec_field = reinterpret_cast<const char *>(
|
||||
rec_get_nth_field(
|
||||
rec, offsets, field_no, &rec_field_len));
|
||||
|
||||
if (UNIV_UNLIKELY(!cs)) {
|
||||
ib::warn() << "Missing collation " << cset;
|
||||
return SIZE_T_MAX;
|
||||
}
|
||||
|
||||
return(cs->cset->numchars(cs, rec_field, rec_field + rec_field_len));
|
||||
}
|
||||
|
||||
/** Avoid the clustered index lookup if all the following conditions
|
||||
are true:
|
||||
1) all columns are in secondary index
|
||||
2) all values for columns that are prefix-only indexes are shorter
|
||||
than the prefix size. This optimization can avoid many IOs for certain schemas.
|
||||
@return true, to avoid clustered index lookup. */
|
||||
static
|
||||
bool row_search_with_covering_prefix(
|
||||
row_prebuilt_t* prebuilt,
|
||||
const rec_t* rec,
|
||||
const ulint* offsets)
|
||||
{
|
||||
const dict_index_t* index = prebuilt->index;
|
||||
ut_ad(!dict_index_is_clust(index));
|
||||
|
||||
if (!srv_prefix_index_cluster_optimization) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Optimization only applicable if there the number of secondary index
|
||||
fields are greater than or equal to number of clustered index fields. */
|
||||
if (prebuilt->n_template > index->n_fields) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ulint i = 0; i < prebuilt->n_template; i++) {
|
||||
mysql_row_templ_t* templ = prebuilt->mysql_template + i;
|
||||
ulint j = templ->rec_prefix_field_no;
|
||||
|
||||
/** Condition (1) : is the field in the index. */
|
||||
if (j == ULINT_UNDEFINED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Condition (2): If this is a prefix index then
|
||||
row's value size shorter than prefix length. */
|
||||
|
||||
if (!templ->rec_field_is_prefix) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ulint rec_size = rec_offs_nth_size(offsets, j);
|
||||
const dict_field_t* field = dict_index_get_nth_field(index, j);
|
||||
ulint max_chars = field->prefix_len / templ->mbmaxlen;
|
||||
|
||||
ut_a(field->prefix_len > 0);
|
||||
|
||||
if (rec_size < max_chars) {
|
||||
/* Record in bytes shorter than the index
|
||||
prefix length in char. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rec_size * templ->mbminlen >= field->prefix_len) {
|
||||
/* Shortest representation string by the
|
||||
byte length of the record is longer than the
|
||||
maximum possible index prefix. */
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t num_chars = rec_field_len_in_chars(
|
||||
field->col, j, rec, offsets);
|
||||
|
||||
if (num_chars >= max_chars) {
|
||||
/* No of chars to store the record exceeds
|
||||
the index prefix character length. */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* If prefix index optimization condition satisfied then
|
||||
for all columns above, use rec_prefix_field_no instead of
|
||||
rec_field_no, and skip the clustered lookup below. */
|
||||
for (ulint i = 0; i < prebuilt->n_template; i++) {
|
||||
mysql_row_templ_t* templ = prebuilt->mysql_template + i;
|
||||
templ->rec_field_no = templ->rec_prefix_field_no;
|
||||
ut_a(templ->rec_field_no != ULINT_UNDEFINED);
|
||||
}
|
||||
|
||||
srv_stats.n_sec_rec_cluster_reads_avoided.inc();
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Searches for rows in the database using cursor.
|
||||
Function is mainly used for tables that are shared across connections and
|
||||
so it employs technique that can help re-construct the rows that
|
||||
|
|
@ -4120,7 +4234,6 @@ row_search_mvcc(
|
|||
ulint* offsets = offsets_;
|
||||
ibool table_lock_waited = FALSE;
|
||||
byte* next_buf = 0;
|
||||
ibool use_clustered_index = FALSE;
|
||||
bool spatial_search = false;
|
||||
|
||||
rec_offs_init(offsets_);
|
||||
|
|
@ -5179,69 +5292,10 @@ locks_ok_del_marked:
|
|||
break;
|
||||
}
|
||||
|
||||
/* Get the clustered index record if needed, if we did not do the
|
||||
search using the clustered index... */
|
||||
|
||||
use_clustered_index =
|
||||
(index != clust_index && prebuilt->need_to_access_clustered);
|
||||
|
||||
if (use_clustered_index && srv_prefix_index_cluster_optimization
|
||||
&& prebuilt->n_template <= index->n_fields) {
|
||||
/* ...but, perhaps avoid the clustered index lookup if
|
||||
all of the following are true:
|
||||
1) all columns are in the secondary index
|
||||
2) all values for columns that are prefix-only
|
||||
indexes are shorter than the prefix size
|
||||
This optimization can avoid many IOs for certain schemas.
|
||||
*/
|
||||
ibool row_contains_all_values = TRUE;
|
||||
uint i;
|
||||
for (i = 0; i < prebuilt->n_template; i++) {
|
||||
/* Condition (1) from above: is the field in the
|
||||
index (prefix or not)? */
|
||||
mysql_row_templ_t* templ =
|
||||
prebuilt->mysql_template + i;
|
||||
ulint secondary_index_field_no =
|
||||
templ->rec_prefix_field_no;
|
||||
if (secondary_index_field_no == ULINT_UNDEFINED) {
|
||||
row_contains_all_values = FALSE;
|
||||
break;
|
||||
}
|
||||
/* Condition (2) from above: if this is a
|
||||
prefix, is this row's value size shorter
|
||||
than the prefix? */
|
||||
if (templ->rec_field_is_prefix) {
|
||||
ulint record_size = rec_offs_nth_size(
|
||||
offsets,
|
||||
secondary_index_field_no);
|
||||
const dict_field_t *field =
|
||||
dict_index_get_nth_field(
|
||||
index,
|
||||
secondary_index_field_no);
|
||||
ut_a(field->prefix_len > 0);
|
||||
if (record_size >= field->prefix_len) {
|
||||
row_contains_all_values = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index != clust_index && prebuilt->need_to_access_clustered) {
|
||||
if (row_search_with_covering_prefix(prebuilt, rec, offsets)) {
|
||||
goto use_covering_index;
|
||||
}
|
||||
/* If (1) and (2) were true for all columns above, use
|
||||
rec_prefix_field_no instead of rec_field_no, and skip
|
||||
the clustered lookup below. */
|
||||
if (row_contains_all_values) {
|
||||
for (i = 0; i < prebuilt->n_template; i++) {
|
||||
mysql_row_templ_t* templ =
|
||||
prebuilt->mysql_template + i;
|
||||
templ->rec_field_no =
|
||||
templ->rec_prefix_field_no;
|
||||
ut_a(templ->rec_field_no != ULINT_UNDEFINED);
|
||||
}
|
||||
use_clustered_index = FALSE;
|
||||
srv_stats.n_sec_rec_cluster_reads_avoided.inc();
|
||||
}
|
||||
}
|
||||
|
||||
if (use_clustered_index) {
|
||||
requires_clust_rec:
|
||||
ut_ad(index != clust_index);
|
||||
/* We use a 'goto' to the preceding label if a consistent
|
||||
|
|
@ -5339,6 +5393,7 @@ requires_clust_rec:
|
|||
}
|
||||
}
|
||||
} else {
|
||||
use_covering_index:
|
||||
result_rec = rec;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_ORACLE_OCI
|
||||
#if (defined(WIN32) || defined(_WIN32) || defined(WINDOWS) || defined(_WINDOWS))
|
||||
#include <Shlwapi.h>
|
||||
#define strcasestr StrStr
|
||||
#endif
|
||||
#include <oci.h>
|
||||
#include "spd_err.h"
|
||||
#include "spd_param.h"
|
||||
|
|
@ -3817,7 +3821,7 @@ int spider_db_oracle_util::open_item_func(
|
|||
{
|
||||
Item_func_conv_charset *item_func_conv_charset =
|
||||
(Item_func_conv_charset *)item_func;
|
||||
CHARSET_INFO *conv_charset = item_func_conv_charset->conv_charset;
|
||||
CHARSET_INFO *conv_charset = item_func_conv_charset->collation.collation;
|
||||
uint cset_length = strlen(conv_charset->csname);
|
||||
if (str->reserve(SPIDER_SQL_USING_LEN + cset_length))
|
||||
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||
|
|
|
|||
|
|
@ -371,6 +371,14 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn(
|
|||
if (direct_sql->access_mode == 0)
|
||||
{
|
||||
#endif
|
||||
if (direct_sql->dbton_id == SPIDER_DBTON_SIZE)
|
||||
{
|
||||
/* Invalid target wrapper */
|
||||
*error_num = ER_SPIDER_INVALID_CONNECT_INFO_NUM;
|
||||
my_printf_error(*error_num, ER_SPIDER_INVALID_CONNECT_INFO_STR,
|
||||
MYF(0), direct_sql->tgt_wrapper);
|
||||
goto error_alloc_conn;
|
||||
}
|
||||
if (!(conn = (SPIDER_CONN *)
|
||||
spider_bulk_malloc(spider_current_trx, 32, MYF(MY_WME | MY_ZEROFILL),
|
||||
&conn, sizeof(*conn),
|
||||
|
|
@ -398,6 +406,14 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn(
|
|||
conn->default_database.init_calc_mem(138);
|
||||
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
|
||||
} else {
|
||||
if (direct_sql->dbton_id == SPIDER_DBTON_SIZE)
|
||||
{
|
||||
/* Invalid target wrapper */
|
||||
*error_num = ER_SPIDER_NOSQL_WRAPPER_IS_INVALID_NUM;
|
||||
my_printf_error(*error_num, ER_SPIDER_NOSQL_WRAPPER_IS_INVALID_STR,
|
||||
MYF(0), direct_sql->tgt_wrapper);
|
||||
goto error_alloc_conn;
|
||||
}
|
||||
if (!(conn = (SPIDER_CONN *)
|
||||
spider_bulk_malloc(spider_current_trx, 33, MYF(MY_WME | MY_ZEROFILL),
|
||||
&conn, sizeof(*conn),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ col3 smallint(5) NOT NULL DEFAULT '1',
|
|||
filler varchar(255) DEFAULT NULL,
|
||||
KEY pk_ersatz(col1,col2,col3),
|
||||
KEY key1 (col1,col2) USING BTREE
|
||||
) ENGINE=TokuDB DEFAULT CHARSET=latin1 PACK_KEYS=1 COMPRESSION=TOKUDB_LZMA;
|
||||
) ENGINE=TokuDB DEFAULT CHARSET=latin1 PACK_KEYS=1;
|
||||
insert into t3 select 1300000000+a, 12345, 7890, 'data' from t2;
|
||||
insert into t3 select 1400000000+a, 12345, 7890, 'data' from t2;
|
||||
insert into t3 select 1410799999+a, 12345, 7890, 'data' from t2;
|
||||
|
|
@ -34,7 +34,7 @@ from t3
|
|||
where col1 <= 1410799999
|
||||
order by col1 desc,col2 desc,col3 desc limit 1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t3 range pk_ersatz,key1 pk_ersatz 4 NULL 2001 Using where; Using index
|
||||
1 SIMPLE t3 range pk_ersatz,key1 pk_ersatz 4 NULL # Using where; Using index
|
||||
# The same query but the constant is bigger.
|
||||
# The query should use range(PRIMARY), not full index scan:
|
||||
explain
|
||||
|
|
@ -43,5 +43,5 @@ from t3
|
|||
where col1 <= 1412199999
|
||||
order by col1 desc, col2 desc, col3 desc limit 1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t3 range pk_ersatz,key1 pk_ersatz 4 NULL 15001 Using where; Using index
|
||||
1 SIMPLE t3 range pk_ersatz,key1 pk_ersatz 4 NULL # Using where; Using index
|
||||
drop table t1,t2,t3;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ CREATE TABLE t3 (
|
|||
filler varchar(255) DEFAULT NULL,
|
||||
KEY pk_ersatz(col1,col2,col3),
|
||||
KEY key1 (col1,col2) USING BTREE
|
||||
) ENGINE=TokuDB DEFAULT CHARSET=latin1 PACK_KEYS=1 COMPRESSION=TOKUDB_LZMA;
|
||||
) ENGINE=TokuDB DEFAULT CHARSET=latin1 PACK_KEYS=1;
|
||||
|
||||
insert into t3 select 1300000000+a, 12345, 7890, 'data' from t2;
|
||||
insert into t3 select 1400000000+a, 12345, 7890, 'data' from t2;
|
||||
|
|
@ -35,6 +35,7 @@ insert into t3 select 1412099999+a, 12345, 7890, 'data' from t2;
|
|||
insert into t3 select 1412199999+a, 12345, 7890, 'data' from t2;
|
||||
|
||||
--echo # The following must use range(PRIMARY):
|
||||
--replace_column 9 #
|
||||
explain
|
||||
select col1,col2,col3
|
||||
from t3
|
||||
|
|
@ -43,6 +44,7 @@ order by col1 desc,col2 desc,col3 desc limit 1;
|
|||
|
||||
--echo # The same query but the constant is bigger.
|
||||
--echo # The query should use range(PRIMARY), not full index scan:
|
||||
--replace_column 9 #
|
||||
explain
|
||||
select col1,col2,col3
|
||||
from t3
|
||||
|
|
|
|||
|
|
@ -216,7 +216,20 @@ buf_dump(
|
|||
buf_dump_status(STATUS_NOTICE, "Dumping buffer pool(s) to %s",
|
||||
full_filename);
|
||||
|
||||
f = fopen(tmp_filename, "w");
|
||||
#if defined(__GLIBC__) || defined(__WIN__) || O_CLOEXEC == 0
|
||||
f = fopen(tmp_filename, "w" STR_O_CLOEXEC);
|
||||
#else
|
||||
{
|
||||
int fd;
|
||||
fd = open(tmp_filename, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, 0640);
|
||||
if (fd >= 0) {
|
||||
f = fdopen(fd, "w");
|
||||
}
|
||||
else {
|
||||
f = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (f == NULL) {
|
||||
buf_dump_status(STATUS_ERR,
|
||||
"Cannot open '%s' for writing: %s",
|
||||
|
|
|
|||
|
|
@ -3685,6 +3685,117 @@ row_search_idx_cond_check(
|
|||
return(result);
|
||||
}
|
||||
|
||||
/** Return the record field length in characters.
|
||||
@param[in] col table column of the field
|
||||
@param[in] field_no field number
|
||||
@param[in] rec physical record
|
||||
@param[in] offsets field offsets in the physical record
|
||||
@return field length in characters. */
|
||||
static
|
||||
size_t
|
||||
rec_field_len_in_chars(
|
||||
const dict_col_t* col,
|
||||
const ulint field_no,
|
||||
const rec_t* rec,
|
||||
const ulint* offsets)
|
||||
{
|
||||
const ulint cset = dtype_get_charset_coll(col->prtype);
|
||||
const CHARSET_INFO* cs = all_charsets[cset];
|
||||
ulint rec_field_len;
|
||||
const char* rec_field = reinterpret_cast<const char *>(
|
||||
rec_get_nth_field(
|
||||
rec, offsets, field_no, &rec_field_len));
|
||||
|
||||
if (UNIV_UNLIKELY(!cs)) {
|
||||
ib_logf(IB_LOG_LEVEL_WARN, "Missing collation " ULINTPF, cset);
|
||||
return SIZE_T_MAX;
|
||||
}
|
||||
|
||||
return(cs->cset->numchars(cs, rec_field, rec_field + rec_field_len));
|
||||
}
|
||||
|
||||
|
||||
/** Avoid the clustered index lookup if all the following conditions
|
||||
are true:
|
||||
1) all columns are in secondary index
|
||||
2) all values for columns that are prefix-only indexes are shorter
|
||||
than the prefix size. This optimization can avoid many IOs for certain schemas.
|
||||
@return true, to avoid clustered index lookup. */
|
||||
static
|
||||
bool row_search_with_covering_prefix(
|
||||
row_prebuilt_t* prebuilt,
|
||||
const rec_t* rec,
|
||||
const ulint* offsets)
|
||||
{
|
||||
const dict_index_t* index = prebuilt->index;
|
||||
ut_ad(!dict_index_is_clust(index));
|
||||
|
||||
if (!srv_prefix_index_cluster_optimization) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Optimization only applicable if the number of secondary index
|
||||
fields are greater than or equal to number of clustered index fields. */
|
||||
if (prebuilt->n_template > index->n_fields) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ulint i = 0; i < prebuilt->n_template; i++) {
|
||||
mysql_row_templ_t* templ = prebuilt->mysql_template + i;
|
||||
ulint j = templ->rec_prefix_field_no;
|
||||
|
||||
/** Condition (1) : is the field in the index. */
|
||||
if (j == ULINT_UNDEFINED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Condition (2): If this is a prefix index then
|
||||
row's value size shorter than prefix length. */
|
||||
|
||||
if (!templ->rec_field_is_prefix) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ulint rec_size = rec_offs_nth_size(offsets, j);
|
||||
const dict_field_t* field = dict_index_get_nth_field(index, j);
|
||||
ulint max_chars = field->prefix_len / templ->mbmaxlen;
|
||||
|
||||
ut_a(field->prefix_len > 0);
|
||||
|
||||
if (rec_size < max_chars) {
|
||||
/* Record in bytes shorter than the index
|
||||
prefix length in char. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rec_size * templ->mbminlen >= field->prefix_len) {
|
||||
/* Shortest representation string by the
|
||||
byte length of the record is longer than the
|
||||
maximum possible index prefix. */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
size_t num_chars = rec_field_len_in_chars(
|
||||
field->col, j, rec, offsets);
|
||||
|
||||
if (num_chars >= max_chars) {
|
||||
/* No of chars to store the record exceeds
|
||||
the index prefix character length. */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (ulint i = 0; i < prebuilt->n_template; i++) {
|
||||
mysql_row_templ_t* templ = prebuilt->mysql_template + i;
|
||||
templ->rec_field_no = templ->rec_prefix_field_no;
|
||||
ut_a(templ->rec_field_no != ULINT_UNDEFINED);
|
||||
}
|
||||
|
||||
srv_stats.n_sec_rec_cluster_reads_avoided.inc();
|
||||
return true;
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Searches for rows in the database. This is used in the interface to
|
||||
MySQL. This function opens a cursor, and also implements fetch next
|
||||
|
|
@ -3748,7 +3859,6 @@ row_search_for_mysql(
|
|||
ulint* offsets = offsets_;
|
||||
ibool table_lock_waited = FALSE;
|
||||
byte* next_buf = 0;
|
||||
bool use_clustered_index = false;
|
||||
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
|
|
@ -4810,71 +4920,10 @@ locks_ok:
|
|||
break;
|
||||
}
|
||||
|
||||
/* Get the clustered index record if needed, if we did not do the
|
||||
search using the clustered index... */
|
||||
|
||||
use_clustered_index =
|
||||
(index != clust_index && prebuilt->need_to_access_clustered);
|
||||
|
||||
if (use_clustered_index && srv_prefix_index_cluster_optimization
|
||||
&& prebuilt->n_template <= index->n_fields) {
|
||||
/* ...but, perhaps avoid the clustered index lookup if
|
||||
all of the following are true:
|
||||
1) all columns are in the secondary index
|
||||
2) all values for columns that are prefix-only
|
||||
indexes are shorter than the prefix size
|
||||
This optimization can avoid many IOs for certain schemas.
|
||||
*/
|
||||
bool row_contains_all_values = true;
|
||||
unsigned int i;
|
||||
for (i = 0; i < prebuilt->n_template; i++) {
|
||||
/* Condition (1) from above: is the field in the
|
||||
index (prefix or not)? */
|
||||
const mysql_row_templ_t* templ =
|
||||
prebuilt->mysql_template + i;
|
||||
ulint secondary_index_field_no =
|
||||
templ->rec_prefix_field_no;
|
||||
if (secondary_index_field_no == ULINT_UNDEFINED) {
|
||||
row_contains_all_values = false;
|
||||
break;
|
||||
}
|
||||
/* Condition (2) from above: if this is a
|
||||
prefix, is this row's value size shorter
|
||||
than the prefix? */
|
||||
if (templ->rec_field_is_prefix) {
|
||||
ulint record_size = rec_offs_nth_size(
|
||||
offsets,
|
||||
secondary_index_field_no);
|
||||
const dict_field_t *field =
|
||||
dict_index_get_nth_field(
|
||||
index,
|
||||
secondary_index_field_no);
|
||||
ut_a(field->prefix_len > 0);
|
||||
if (record_size >= field->prefix_len
|
||||
/ templ->mbmaxlen) {
|
||||
row_contains_all_values = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index != clust_index && prebuilt->need_to_access_clustered) {
|
||||
if (row_search_with_covering_prefix(prebuilt, rec, offsets)) {
|
||||
goto use_covering_index;
|
||||
}
|
||||
/* If (1) and (2) were true for all columns above, use
|
||||
rec_prefix_field_no instead of rec_field_no, and skip
|
||||
the clustered lookup below. */
|
||||
if (row_contains_all_values) {
|
||||
for (i = 0; i < prebuilt->n_template; i++) {
|
||||
mysql_row_templ_t* templ =
|
||||
prebuilt->mysql_template + i;
|
||||
templ->rec_field_no =
|
||||
templ->rec_prefix_field_no;
|
||||
ut_a(templ->rec_field_no != ULINT_UNDEFINED);
|
||||
}
|
||||
use_clustered_index = false;
|
||||
srv_stats.n_sec_rec_cluster_reads_avoided.inc();
|
||||
}
|
||||
}
|
||||
|
||||
if (use_clustered_index) {
|
||||
|
||||
requires_clust_rec:
|
||||
ut_ad(index != clust_index);
|
||||
/* We use a 'goto' to the preceding label if a consistent
|
||||
|
|
@ -4960,6 +5009,7 @@ requires_clust_rec:
|
|||
}
|
||||
}
|
||||
} else {
|
||||
use_covering_index:
|
||||
result_rec = rec;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue