mirror of
https://github.com/MariaDB/server.git
synced 2026-05-16 03:47:17 +02:00
5.6.37
This commit is contained in:
parent
0af9818240
commit
d36bd69790
7 changed files with 176 additions and 52 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2008, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
|
@ -1976,11 +1976,14 @@ ib_cursor_read_row(
|
|||
|
||||
page_format = static_cast<ib_bool_t>(
|
||||
dict_table_is_comp(tuple->index->table));
|
||||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
|
||||
if (prebuilt->innodb_api_rec &&
|
||||
prebuilt->innodb_api_rec != rec) {
|
||||
rec = prebuilt->innodb_api_rec;
|
||||
if (!rec_get_deleted_flag(rec, page_format)) {
|
||||
if (prebuilt->innodb_api &&
|
||||
prebuilt->innodb_api_rec != NULL) {
|
||||
rec =prebuilt->innodb_api_rec;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rec_get_deleted_flag(rec, page_format)) {
|
||||
|
|
@ -2017,6 +2020,10 @@ ib_cursor_position(
|
|||
|
||||
buf = static_cast<unsigned char*>(mem_alloc(UNIV_PAGE_SIZE));
|
||||
|
||||
if (prebuilt->innodb_api) {
|
||||
prebuilt->cursor_heap = cursor->heap;
|
||||
}
|
||||
|
||||
/* We want to position at one of the ends, row_search_for_mysql()
|
||||
uses the search_tuple fields to work out what to do. */
|
||||
dtuple_set_n_fields(prebuilt->search_tuple, 0);
|
||||
|
|
@ -2071,6 +2078,9 @@ ib_cursor_next(
|
|||
row_prebuilt_t* prebuilt = cursor->prebuilt;
|
||||
byte buf[UNIV_PAGE_SIZE_MAX];
|
||||
|
||||
if (prebuilt->innodb_api) {
|
||||
prebuilt->cursor_heap = cursor->heap;
|
||||
}
|
||||
/* We want to move to the next record */
|
||||
dtuple_set_n_fields(prebuilt->search_tuple, 0);
|
||||
|
||||
|
|
@ -2123,6 +2133,9 @@ ib_cursor_moveto(
|
|||
|
||||
buf = static_cast<unsigned char*>(mem_alloc(UNIV_PAGE_SIZE));
|
||||
|
||||
if (prebuilt->innodb_api) {
|
||||
prebuilt->cursor_heap = cursor->heap;
|
||||
}
|
||||
err = static_cast<ib_err_t>(row_search_for_mysql(
|
||||
buf, ib_srch_mode, prebuilt, cursor->match_mode, 0));
|
||||
|
||||
|
|
|
|||
|
|
@ -8321,6 +8321,27 @@ ha_innobase::ft_init_ext(
|
|||
return((FT_INFO*) fts_hdl);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Copy a cached MySQL row.
|
||||
If requested, also avoids overwriting non-read columns.
|
||||
@param[out] buf Row in MySQL format.
|
||||
@param[in] cached_row Which row to copy.
|
||||
@param[in] rec_len Record length. */
|
||||
void
|
||||
ha_innobase::copy_cached_row(
|
||||
uchar* buf,
|
||||
const uchar* cached_row,
|
||||
uint rec_len)
|
||||
{
|
||||
if (prebuilt->keep_other_fields_on_keyread) {
|
||||
row_sel_copy_cached_fields_for_mysql(buf, cached_row,
|
||||
prebuilt);
|
||||
} else {
|
||||
memcpy(buf, cached_row, rec_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************//**
|
||||
Set up search tuple for a query through FTS_DOC_ID_INDEX on
|
||||
supplied Doc ID. This is used by MySQL to retrieve the documents
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
|
@ -142,6 +142,10 @@ class ha_innobase: public handler
|
|||
int index_first(uchar * buf);
|
||||
int index_last(uchar * buf);
|
||||
|
||||
/* Copy a cached MySQL row. If requested, also avoids
|
||||
overwriting non-read columns. */
|
||||
void copy_cached_row(uchar *to_rec, const uchar *from_rec,
|
||||
uint rec_length);
|
||||
int rnd_init(bool scan);
|
||||
int rnd_end();
|
||||
int rnd_next(uchar *buf);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
|
@ -723,6 +723,8 @@ struct row_prebuilt_t {
|
|||
mem_heap_t* heap; /*!< memory heap from which
|
||||
these auxiliary structures are
|
||||
allocated when needed */
|
||||
mem_heap_t* cursor_heap; /*!< memory heap from which
|
||||
innodb_api_buf is allocated per session*/
|
||||
ins_node_t* ins_node; /*!< Innobase SQL insert node
|
||||
used to perform inserts
|
||||
to the table */
|
||||
|
|
@ -873,6 +875,9 @@ struct row_prebuilt_t {
|
|||
unsigned innodb_api:1; /*!< whether this is a InnoDB API
|
||||
query */
|
||||
const rec_t* innodb_api_rec; /*!< InnoDB API search result */
|
||||
void* innodb_api_buf; /*!< Buffer holding copy of the physical
|
||||
Innodb API search record */
|
||||
ulint innodb_api_rec_size; /*!< Size of the Innodb API record */
|
||||
byte* srch_key_val1; /*!< buffer used in converting
|
||||
search key values from MySQL format
|
||||
to InnoDB format.*/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
|
@ -205,6 +205,18 @@ struct sel_buf_t{
|
|||
when data != NULL */
|
||||
};
|
||||
|
||||
/** Copy used fields from cached row.
|
||||
Copy cache record field by field, don't touch fields that
|
||||
are not covered by current key.
|
||||
@param[out] buf Where to copy the MySQL row.
|
||||
@param[in] cached_rec What to copy (in MySQL row format).
|
||||
@param[in] prebuilt prebuilt struct. */
|
||||
void
|
||||
row_sel_copy_cached_fields_for_mysql(
|
||||
byte* buf,
|
||||
const byte* cached_rec,
|
||||
row_prebuilt_t* prebuilt);
|
||||
|
||||
/** Query plan */
|
||||
struct plan_t{
|
||||
dict_table_t* table; /*!< table struct in the dictionary
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
|
@ -1462,6 +1462,8 @@ row_merge_read_clustered_index(
|
|||
row_ext_t* ext;
|
||||
page_cur_t* cur = btr_pcur_get_page_cur(&pcur);
|
||||
|
||||
mem_heap_empty(row_heap);
|
||||
|
||||
page_cur_move_to_next(cur);
|
||||
|
||||
if (page_cur_is_after_last(cur)) {
|
||||
|
|
@ -1885,8 +1887,6 @@ write_buffers:
|
|||
if (err != DB_SUCCESS) {
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
mem_heap_empty(row_heap);
|
||||
}
|
||||
|
||||
func_exit:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
|
|
@ -2555,47 +2555,51 @@ row_sel_store_row_id_to_prebuilt(
|
|||
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Convert a non-SQL-NULL field from Innobase format to MySQL format. */
|
||||
# define row_sel_field_store_in_mysql_format(dest,templ,idx,field,src,len) \
|
||||
row_sel_field_store_in_mysql_format_func(dest,templ,idx,field,src,len)
|
||||
# define row_sel_field_store_in_mysql_format(dest,templ,idx,field,src,len,sec) \
|
||||
row_sel_field_store_in_mysql_format_func(dest,templ,idx,field,src,len,sec)
|
||||
#else /* UNIV_DEBUG */
|
||||
/** Convert a non-SQL-NULL field from Innobase format to MySQL format. */
|
||||
# define row_sel_field_store_in_mysql_format(dest,templ,idx,field,src,len) \
|
||||
row_sel_field_store_in_mysql_format_func(dest,templ,src,len)
|
||||
# define row_sel_field_store_in_mysql_format(dest,templ,idx,field,src,len,sec) \
|
||||
row_sel_field_store_in_mysql_format_func(dest,templ,src,len,sec)
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/**************************************************************//**
|
||||
Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
|
||||
function is row_mysql_store_col_in_innobase_format() in row0mysql.cc. */
|
||||
/** Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
|
||||
function is row_mysql_store_col_in_innobase_format() in row0mysql.cc.
|
||||
@param[in,out] dest buffer where to store; NOTE
|
||||
that BLOBs are not in themselves stored
|
||||
here: the caller must allocate and copy
|
||||
the BLOB into buffer before, and pass
|
||||
the pointer to the BLOB in 'data'
|
||||
@param[in] templ MySQL column template. Its following fields
|
||||
are referenced: type, is_unsigned, mysql_col_len,
|
||||
mbminlen, mbmaxlen
|
||||
@param[in] index InnoDB index
|
||||
@param[in] field_no templ->rec_field_no or templ->clust_rec_field_no
|
||||
or templ->icp_rec_field_no
|
||||
@param[in] data data to store
|
||||
@param[in] len length of the data
|
||||
@param[in] sec_field secondary index field no if the secondary index
|
||||
record but the prebuilt template is in
|
||||
clustered index format and used only for end
|
||||
range comparison. */
|
||||
static MY_ATTRIBUTE((nonnull))
|
||||
void
|
||||
row_sel_field_store_in_mysql_format_func(
|
||||
/*=====================================*/
|
||||
byte* dest, /*!< in/out: buffer where to store; NOTE
|
||||
that BLOBs are not in themselves
|
||||
stored here: the caller must allocate
|
||||
and copy the BLOB into buffer before,
|
||||
and pass the pointer to the BLOB in
|
||||
'data' */
|
||||
byte* dest,
|
||||
const mysql_row_templ_t* templ,
|
||||
/*!< in: MySQL column template.
|
||||
Its following fields are referenced:
|
||||
type, is_unsigned, mysql_col_len,
|
||||
mbminlen, mbmaxlen */
|
||||
#ifdef UNIV_DEBUG
|
||||
const dict_index_t* index,
|
||||
/*!< in: InnoDB index */
|
||||
ulint field_no,
|
||||
/*!< in: templ->rec_field_no or
|
||||
templ->clust_rec_field_no or
|
||||
templ->icp_rec_field_no */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const byte* data, /*!< in: data to store */
|
||||
ulint len) /*!< in: length of the data */
|
||||
const byte* data,
|
||||
ulint len,
|
||||
ulint sec_field)
|
||||
{
|
||||
byte* ptr;
|
||||
#ifdef UNIV_DEBUG
|
||||
const dict_field_t* field
|
||||
= dict_index_get_nth_field(index, field_no);
|
||||
bool clust_templ_for_sec = (sec_field != ULINT_UNDEFINED);
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
ut_ad(len != UNIV_SQL_NULL);
|
||||
|
|
@ -2709,7 +2713,8 @@ row_sel_field_store_in_mysql_format_func(
|
|||
containing UTF-8 ENUM columns due to Bug #9526. */
|
||||
ut_ad(!templ->mbmaxlen
|
||||
|| !(templ->mysql_col_len % templ->mbmaxlen));
|
||||
ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len
|
||||
ut_ad(clust_templ_for_sec
|
||||
|| len * templ->mbmaxlen >= templ->mysql_col_len
|
||||
|| (field_no == templ->icp_rec_field_no
|
||||
&& field->prefix_len > 0));
|
||||
ut_ad(!(field->prefix_len % templ->mbmaxlen));
|
||||
|
|
@ -2737,21 +2742,26 @@ row_sel_field_store_in_mysql_format_func(
|
|||
case DATA_DECIMAL:
|
||||
/* Above are the valid column types for MySQL data. */
|
||||
#endif /* UNIV_DEBUG */
|
||||
/* If sec_field value is present then mapping of
|
||||
secondary index records to clustered index template
|
||||
happens for end range comparison. So length can
|
||||
vary according to secondary index record length. */
|
||||
ut_ad(field->prefix_len
|
||||
? field->prefix_len == len
|
||||
: templ->mysql_col_len == len);
|
||||
: (clust_templ_for_sec ?
|
||||
1 : (templ->mysql_col_len == len)));
|
||||
memcpy(dest, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Convert a field from Innobase format to MySQL format. */
|
||||
# define row_sel_store_mysql_field(m,p,r,i,o,f,t,c) \
|
||||
row_sel_store_mysql_field_func(m,p,r,i,o,f,t,c)
|
||||
# define row_sel_store_mysql_field(m,p,r,i,o,f,t,s) \
|
||||
row_sel_store_mysql_field_func(m,p,r,i,o,f,t,s)
|
||||
#else /* UNIV_DEBUG */
|
||||
/** Convert a field from Innobase format to MySQL format. */
|
||||
# define row_sel_store_mysql_field(m,p,r,i,o,f,t,c) \
|
||||
row_sel_store_mysql_field_func(m,p,r,o,f,t,c)
|
||||
# define row_sel_store_mysql_field(m,p,r,i,o,f,t,s) \
|
||||
row_sel_store_mysql_field_func(m,p,r,o,f,t,s)
|
||||
#endif /* UNIV_DEBUG */
|
||||
/** Convert a field in the Innobase format to a field in the MySQL format.
|
||||
@param[out] mysql_rec record in the MySQL format
|
||||
|
|
@ -2766,7 +2776,7 @@ row_sel_field_store_in_mysql_format_func(
|
|||
or sec field no if clust_templ_for_sec
|
||||
is TRUE
|
||||
@param[in] templ row template
|
||||
@param[in] clust_templ_for_sec TRUE if rec belongs to secondary index
|
||||
@param[in] sec_field_no field_no if rec belongs to secondary index
|
||||
but prebuilt template is in clustered
|
||||
index format and used only for end
|
||||
range comparison. */
|
||||
|
|
@ -2782,10 +2792,12 @@ row_sel_store_mysql_field_func(
|
|||
const ulint* offsets,
|
||||
ulint field_no,
|
||||
const mysql_row_templ_t*templ,
|
||||
bool clust_templ_for_sec)
|
||||
ulint sec_field_no)
|
||||
{
|
||||
const byte* data;
|
||||
ulint len;
|
||||
ulint clust_field_no;
|
||||
bool clust_templ_for_sec = (sec_field_no != ULINT_UNDEFINED);
|
||||
|
||||
ut_ad(prebuilt->default_rec);
|
||||
ut_ad(templ);
|
||||
|
|
@ -2796,7 +2808,14 @@ row_sel_store_mysql_field_func(
|
|||
|| field_no == templ->rec_field_no
|
||||
|| field_no == templ->icp_rec_field_no);
|
||||
ut_ad(rec_offs_validate(rec,
|
||||
clust_templ_for_sec == true ? prebuilt->index : index, offsets));
|
||||
clust_templ_for_sec ? prebuilt->index : index, offsets));
|
||||
|
||||
/* If sec_field_no is present then extract the data from record
|
||||
using secondary field no. */
|
||||
if (clust_templ_for_sec) {
|
||||
clust_field_no = field_no;
|
||||
field_no = sec_field_no;
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) {
|
||||
|
||||
|
|
@ -2845,7 +2864,8 @@ row_sel_store_mysql_field_func(
|
|||
|
||||
row_sel_field_store_in_mysql_format(
|
||||
mysql_rec + templ->mysql_col_offset,
|
||||
templ, index, field_no, data, len);
|
||||
templ, index, field_no, data, len,
|
||||
ULINT_UNDEFINED);
|
||||
|
||||
if (heap != prebuilt->blob_heap) {
|
||||
mem_heap_free(heap);
|
||||
|
|
@ -2893,9 +2913,14 @@ row_sel_store_mysql_field_func(
|
|||
mem_heap_dup(prebuilt->blob_heap, data, len));
|
||||
}
|
||||
|
||||
/* Reassign the clustered index field no. */
|
||||
if (clust_templ_for_sec) {
|
||||
field_no = clust_field_no;
|
||||
}
|
||||
|
||||
row_sel_field_store_in_mysql_format(
|
||||
mysql_rec + templ->mysql_col_offset,
|
||||
templ, index, field_no, data, len);
|
||||
templ, index, field_no, data, len, sec_field_no);
|
||||
}
|
||||
|
||||
ut_ad(len != UNIV_SQL_NULL);
|
||||
|
|
@ -2967,6 +2992,8 @@ row_sel_store_mysql_rec(
|
|||
= rec_clust
|
||||
? templ->clust_rec_field_no
|
||||
: templ->rec_field_no;
|
||||
ulint sec_field_no = ULINT_UNDEFINED;
|
||||
|
||||
/* We should never deliver column prefixes to MySQL,
|
||||
except for evaluating innobase_index_cond(). */
|
||||
ut_ad(dict_index_get_nth_field(index, field_no)->prefix_len
|
||||
|
|
@ -2983,13 +3010,13 @@ row_sel_store_mysql_rec(
|
|||
|
||||
ut_ad(templ->rec_field_no == templ->clust_rec_field_no);
|
||||
|
||||
field_no = it - template_col.begin();
|
||||
sec_field_no = it - template_col.begin();
|
||||
}
|
||||
|
||||
if (!row_sel_store_mysql_field(mysql_rec, prebuilt,
|
||||
rec, index, offsets,
|
||||
field_no, templ,
|
||||
clust_templ_for_sec)) {
|
||||
sec_field_no)) {
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
|
@ -2999,7 +3026,8 @@ row_sel_store_mysql_rec(
|
|||
NOTE, the record must be cluster index record. Secondary index
|
||||
might not have the Doc ID */
|
||||
if (dict_table_has_fts_index(prebuilt->table)
|
||||
&& dict_index_is_clust(index)) {
|
||||
&& dict_index_is_clust(index)
|
||||
&& !clust_templ_for_sec) {
|
||||
|
||||
prebuilt->fts_doc_id = fts_get_doc_id_from_rec(
|
||||
prebuilt->table, rec, NULL);
|
||||
|
|
@ -3370,6 +3398,36 @@ row_sel_copy_cached_field_for_mysql(
|
|||
ut_memcpy(buf, cache, len);
|
||||
}
|
||||
|
||||
/** Copy used fields from cached row.
|
||||
Copy cache record field by field, don't touch fields that
|
||||
are not covered by current key.
|
||||
@param[out] buf Where to copy the MySQL row.
|
||||
@param[in] cached_rec What to copy (in MySQL row format).
|
||||
@param[in] prebuilt prebuilt struct. */
|
||||
void
|
||||
row_sel_copy_cached_fields_for_mysql(
|
||||
byte* buf,
|
||||
const byte* cached_rec,
|
||||
row_prebuilt_t* prebuilt)
|
||||
{
|
||||
const mysql_row_templ_t*templ;
|
||||
ulint i;
|
||||
for (i = 0; i < prebuilt->n_template; i++) {
|
||||
templ = prebuilt->mysql_template + i;
|
||||
|
||||
row_sel_copy_cached_field_for_mysql(
|
||||
buf, cached_rec, templ);
|
||||
/* Copy NULL bit of the current field from cached_rec
|
||||
to buf */
|
||||
if (templ->mysql_null_bit_mask) {
|
||||
buf[templ->mysql_null_byte_offset]
|
||||
^= (buf[templ->mysql_null_byte_offset]
|
||||
^ cached_rec[templ->mysql_null_byte_offset])
|
||||
& (byte) templ->mysql_null_bit_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Pops a cached row for MySQL from the fetch cache. */
|
||||
UNIV_INLINE
|
||||
|
|
@ -3629,7 +3687,7 @@ row_search_idx_cond_check(
|
|||
if (!row_sel_store_mysql_field(mysql_rec, prebuilt,
|
||||
rec, prebuilt->index, offsets,
|
||||
templ->icp_rec_field_no,
|
||||
templ, false)) {
|
||||
templ, ULINT_UNDEFINED)) {
|
||||
return(ICP_NO_MATCH);
|
||||
}
|
||||
}
|
||||
|
|
@ -5086,8 +5144,19 @@ idx_cond_failed:
|
|||
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
|
||||
if (prebuilt->innodb_api) {
|
||||
prebuilt->innodb_api_rec = result_rec;
|
||||
if (prebuilt->innodb_api
|
||||
&& (btr_pcur_get_rec(pcur) != result_rec)) {
|
||||
ulint rec_size = rec_offs_size(offsets);
|
||||
if (!prebuilt->innodb_api_rec_size ||
|
||||
(prebuilt->innodb_api_rec_size < rec_size)) {
|
||||
prebuilt->innodb_api_buf =
|
||||
static_cast<byte*>
|
||||
(mem_heap_alloc(prebuilt->cursor_heap,rec_size));
|
||||
prebuilt->innodb_api_rec_size = rec_size;
|
||||
}
|
||||
prebuilt->innodb_api_rec =
|
||||
rec_copy(
|
||||
prebuilt->innodb_api_buf, result_rec, offsets);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue