Commit cbd62fee authored by Vicențiu Ciorbaru's avatar Vicențiu Ciorbaru

Merge branch 'merge-xtradb-5.6' into 10.0

parents 745cd57a b4606367
/***************************************************************************** /*****************************************************************************
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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -1988,11 +1988,14 @@ ib_cursor_read_row( ...@@ -1988,11 +1988,14 @@ ib_cursor_read_row(
page_format = static_cast<ib_bool_t>( page_format = static_cast<ib_bool_t>(
dict_table_is_comp(tuple->index->table)); dict_table_is_comp(tuple->index->table));
rec = btr_pcur_get_rec(pcur); rec = btr_pcur_get_rec(pcur);
if (prebuilt->innodb_api_rec && if (!rec_get_deleted_flag(rec, page_format)) {
prebuilt->innodb_api_rec != rec) { if (prebuilt->innodb_api &&
rec = prebuilt->innodb_api_rec; prebuilt->innodb_api_rec != NULL) {
rec =prebuilt->innodb_api_rec;
}
} }
if (!rec_get_deleted_flag(rec, page_format)) { if (!rec_get_deleted_flag(rec, page_format)) {
...@@ -2029,6 +2032,10 @@ ib_cursor_position( ...@@ -2029,6 +2032,10 @@ ib_cursor_position(
buf = static_cast<unsigned char*>(mem_alloc(UNIV_PAGE_SIZE)); 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() /* We want to position at one of the ends, row_search_for_mysql()
uses the search_tuple fields to work out what to do. */ uses the search_tuple fields to work out what to do. */
dtuple_set_n_fields(prebuilt->search_tuple, 0); dtuple_set_n_fields(prebuilt->search_tuple, 0);
...@@ -2083,6 +2090,9 @@ ib_cursor_next( ...@@ -2083,6 +2090,9 @@ ib_cursor_next(
row_prebuilt_t* prebuilt = cursor->prebuilt; row_prebuilt_t* prebuilt = cursor->prebuilt;
byte buf[UNIV_PAGE_SIZE_MAX]; byte buf[UNIV_PAGE_SIZE_MAX];
if (prebuilt->innodb_api) {
prebuilt->cursor_heap = cursor->heap;
}
/* We want to move to the next record */ /* We want to move to the next record */
dtuple_set_n_fields(prebuilt->search_tuple, 0); dtuple_set_n_fields(prebuilt->search_tuple, 0);
...@@ -2135,6 +2145,9 @@ ib_cursor_moveto( ...@@ -2135,6 +2145,9 @@ ib_cursor_moveto(
buf = static_cast<unsigned char*>(mem_alloc(UNIV_PAGE_SIZE)); 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( err = static_cast<ib_err_t>(row_search_for_mysql(
buf, ib_srch_mode, prebuilt, cursor->match_mode, 0)); buf, ib_srch_mode, prebuilt, cursor->match_mode, 0));
......
...@@ -9599,6 +9599,27 @@ ha_innobase::ft_init_ext( ...@@ -9599,6 +9599,27 @@ ha_innobase::ft_init_ext(
return((FT_INFO*) fts_hdl); 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 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 supplied Doc ID. This is used by MySQL to retrieve the documents
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation. Copyright (c) 2013, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
...@@ -144,6 +144,10 @@ class ha_innobase: public handler ...@@ -144,6 +144,10 @@ class ha_innobase: public handler
int index_first(uchar * buf); int index_first(uchar * buf);
int index_last(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);
bool has_gap_locks() const { return true; } bool has_gap_locks() const { return true; }
int rnd_init(bool scan); int rnd_init(bool scan);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
...@@ -735,6 +735,8 @@ struct row_prebuilt_t { ...@@ -735,6 +735,8 @@ struct row_prebuilt_t {
mem_heap_t* heap; /*!< memory heap from which mem_heap_t* heap; /*!< memory heap from which
these auxiliary structures are these auxiliary structures are
allocated when needed */ 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 ins_node_t* ins_node; /*!< Innobase SQL insert node
used to perform inserts used to perform inserts
to the table */ to the table */
...@@ -885,6 +887,9 @@ struct row_prebuilt_t { ...@@ -885,6 +887,9 @@ struct row_prebuilt_t {
unsigned innodb_api:1; /*!< whether this is a InnoDB API unsigned innodb_api:1; /*!< whether this is a InnoDB API
query */ query */
const rec_t* innodb_api_rec; /*!< InnoDB API search result */ 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 byte* srch_key_val1; /*!< buffer used in converting
search key values from MySQL format search key values from MySQL format
to InnoDB format.*/ to InnoDB format.*/
......
/***************************************************************************** /*****************************************************************************
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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -205,6 +205,18 @@ struct sel_buf_t{ ...@@ -205,6 +205,18 @@ struct sel_buf_t{
when data != NULL */ 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 */ /** Query plan */
struct plan_t{ struct plan_t{
dict_table_t* table; /*!< table struct in the dictionary dict_table_t* table; /*!< table struct in the dictionary
......
...@@ -48,7 +48,7 @@ Created 1/20/1994 Heikki Tuuri ...@@ -48,7 +48,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_BUGFIX 36 #define INNODB_VERSION_BUGFIX 36
#ifndef PERCONA_INNODB_VERSION #ifndef PERCONA_INNODB_VERSION
#define PERCONA_INNODB_VERSION 82.1 #define PERCONA_INNODB_VERSION 82.2
#endif #endif
/* Enable UNIV_LOG_ARCHIVE in XtraDB */ /* Enable UNIV_LOG_ARCHIVE in XtraDB */
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation. Copyright (c) 2014, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
...@@ -1459,6 +1459,8 @@ row_merge_read_clustered_index( ...@@ -1459,6 +1459,8 @@ row_merge_read_clustered_index(
row_ext_t* ext; row_ext_t* ext;
page_cur_t* cur = btr_pcur_get_page_cur(&pcur); page_cur_t* cur = btr_pcur_get_page_cur(&pcur);
mem_heap_empty(row_heap);
page_cur_move_to_next(cur); page_cur_move_to_next(cur);
if (page_cur_is_after_last(cur)) { if (page_cur_is_after_last(cur)) {
...@@ -1888,8 +1890,6 @@ row_merge_read_clustered_index( ...@@ -1888,8 +1890,6 @@ row_merge_read_clustered_index(
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
goto func_exit; goto func_exit;
} }
mem_heap_empty(row_heap);
} }
func_exit: func_exit:
......
/***************************************************************************** /*****************************************************************************
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. Copyright (c) 2008, Google Inc.
Copyright (c) 2017, MariaDB Corporation. Copyright (c) 2017, MariaDB Corporation.
...@@ -2569,31 +2569,30 @@ row_sel_store_row_id_to_prebuilt( ...@@ -2569,31 +2569,30 @@ row_sel_store_row_id_to_prebuilt(
(dest,templ,src,len) (dest,templ,src,len)
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/**************************************************************//** /** Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
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.
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
*/
static MY_ATTRIBUTE((nonnull)) static MY_ATTRIBUTE((nonnull))
void void
row_sel_field_store_in_mysql_format_func( row_sel_field_store_in_mysql_format_func(
/*=====================================*/ byte* dest,
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' */
const mysql_row_templ_t* templ, 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 #ifdef UNIV_DEBUG
const dict_index_t* index, const dict_index_t* index,
/*!< in: InnoDB index */
ulint field_no, ulint field_no,
/*!< in: templ->rec_field_no or
templ->clust_rec_field_no or
templ->icp_rec_field_no */
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
const byte* data, /*!< in: data to store */ const byte* data, /*!< in: data to store */
ulint len) /*!< in: length of the data */ ulint len) /*!< in: length of the data */
...@@ -2602,6 +2601,7 @@ row_sel_field_store_in_mysql_format_func( ...@@ -2602,6 +2601,7 @@ row_sel_field_store_in_mysql_format_func(
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
const dict_field_t* field const dict_field_t* field
= dict_index_get_nth_field(index, field_no); = dict_index_get_nth_field(index, field_no);
bool clust_templ_for_sec = (sec_field != ULINT_UNDEFINED);
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
ut_ad(len != UNIV_SQL_NULL); ut_ad(len != UNIV_SQL_NULL);
...@@ -2715,7 +2715,8 @@ row_sel_field_store_in_mysql_format_func( ...@@ -2715,7 +2715,8 @@ row_sel_field_store_in_mysql_format_func(
containing UTF-8 ENUM columns due to Bug #9526. */ containing UTF-8 ENUM columns due to Bug #9526. */
ut_ad(!templ->mbmaxlen ut_ad(!templ->mbmaxlen
|| !(templ->mysql_col_len % 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_no == templ->icp_rec_field_no
&& field->prefix_len > 0) && field->prefix_len > 0)
|| templ->rec_field_is_prefix); || templ->rec_field_is_prefix);
...@@ -2744,9 +2745,14 @@ row_sel_field_store_in_mysql_format_func( ...@@ -2744,9 +2745,14 @@ row_sel_field_store_in_mysql_format_func(
case DATA_DECIMAL: case DATA_DECIMAL:
/* Above are the valid column types for MySQL data. */ /* Above are the valid column types for MySQL data. */
#endif /* UNIV_DEBUG */ #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 ut_ad(field->prefix_len
? field->prefix_len == len ? field->prefix_len == len
: templ->mysql_col_len == len); : (clust_templ_for_sec ?
1 : (templ->mysql_col_len == len)));
memcpy(dest, data, len); memcpy(dest, data, len);
} }
} }
...@@ -2789,6 +2795,8 @@ row_sel_store_mysql_field_func( ...@@ -2789,6 +2795,8 @@ row_sel_store_mysql_field_func(
{ {
const byte* data; const byte* data;
ulint len; ulint len;
ulint clust_field_no;
bool clust_templ_for_sec = (sec_field_no != ULINT_UNDEFINED);
ut_ad(prebuilt->default_rec); ut_ad(prebuilt->default_rec);
ut_ad(templ); ut_ad(templ);
...@@ -2897,6 +2905,11 @@ row_sel_store_mysql_field_func( ...@@ -2897,6 +2905,11 @@ row_sel_store_mysql_field_func(
mem_heap_dup(prebuilt->blob_heap, data, len)); 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( row_sel_field_store_in_mysql_format(
mysql_rec + templ->mysql_col_offset, mysql_rec + templ->mysql_col_offset,
templ, index, field_no, data, len); templ, index, field_no, data, len);
...@@ -2953,6 +2966,8 @@ row_sel_store_mysql_rec( ...@@ -2953,6 +2966,8 @@ row_sel_store_mysql_rec(
= rec_clust = rec_clust
? templ->clust_rec_field_no ? templ->clust_rec_field_no
: templ->rec_field_no; : templ->rec_field_no;
ulint sec_field_no = ULINT_UNDEFINED;
/* We should never deliver column prefixes to MySQL, /* We should never deliver column prefixes to MySQL,
except for evaluating innobase_index_cond() and if the prefix except for evaluating innobase_index_cond() and if the prefix
index is longer than the actual row data. */ index is longer than the actual row data. */
...@@ -2973,7 +2988,8 @@ row_sel_store_mysql_rec( ...@@ -2973,7 +2988,8 @@ row_sel_store_mysql_rec(
NOTE, the record must be cluster index record. Secondary index NOTE, the record must be cluster index record. Secondary index
might not have the Doc ID */ might not have the Doc ID */
if (dict_table_has_fts_index(prebuilt->table) 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->fts_doc_id = fts_get_doc_id_from_rec(
prebuilt->table, rec, NULL); prebuilt->table, rec, NULL);
...@@ -3346,6 +3362,36 @@ row_sel_copy_cached_field_for_mysql( ...@@ -3346,6 +3362,36 @@ row_sel_copy_cached_field_for_mysql(
ut_memcpy(buf, cache, len); 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. */ Pops a cached row for MySQL from the fetch cache. */
UNIV_INLINE UNIV_INLINE
...@@ -5068,8 +5114,19 @@ row_search_for_mysql( ...@@ -5068,8 +5114,19 @@ row_search_for_mysql(
btr_pcur_store_position(pcur, &mtr); btr_pcur_store_position(pcur, &mtr);
if (prebuilt->innodb_api) { if (prebuilt->innodb_api
prebuilt->innodb_api_rec = result_rec; && (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);
} }
} }
......
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