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
the terms of the GNU General Public License as published by the Free Software
......@@ -1988,11 +1988,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)) {
......@@ -2029,6 +2032,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);
......@@ -2083,6 +2090,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);
......@@ -2135,6 +2145,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));
......
......@@ -9599,6 +9599,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
......
/*****************************************************************************
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.
This program is free software; you can redistribute it and/or modify it under
......@@ -144,6 +144,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);
bool has_gap_locks() const { return true; }
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.
This program is free software; you can redistribute it and/or modify it under
......@@ -735,6 +735,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 */
......@@ -885,6 +887,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.*/
......
/*****************************************************************************
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
......
......@@ -48,7 +48,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_BUGFIX 36
#ifndef PERCONA_INNODB_VERSION
#define PERCONA_INNODB_VERSION 82.1
#define PERCONA_INNODB_VERSION 82.2
#endif
/* 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.
This program is free software; you can redistribute it and/or modify it under
......@@ -1459,6 +1459,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)) {
......@@ -1888,8 +1890,6 @@ row_merge_read_clustered_index(
if (err != DB_SUCCESS) {
goto func_exit;
}
mem_heap_empty(row_heap);
}
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) 2017, MariaDB Corporation.
......@@ -2569,31 +2569,30 @@ row_sel_store_row_id_to_prebuilt(
(dest,templ,src,len)
#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
*/
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 */
......@@ -2602,6 +2601,7 @@ row_sel_field_store_in_mysql_format_func(
#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);
......@@ -2715,7 +2715,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)
|| templ->rec_field_is_prefix);
......@@ -2744,9 +2745,14 @@ 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);
}
}
......@@ -2789,6 +2795,8 @@ row_sel_store_mysql_field_func(
{
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);
......@@ -2897,6 +2905,11 @@ 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);
......@@ -2953,6 +2966,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() and if the prefix
index is longer than the actual row data. */
......@@ -2973,7 +2988,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);
......@@ -3346,6 +3362,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
......@@ -5068,8 +5114,19 @@ row_search_for_mysql(
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);
}
}
......
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