summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--storage/innobase/api/api0api.cc21
-rw-r--r--storage/innobase/handler/ha_innodb.cc21
-rw-r--r--storage/innobase/handler/ha_innodb.h6
-rw-r--r--storage/innobase/include/row0mysql.h7
-rw-r--r--storage/innobase/include/row0sel.h14
-rw-r--r--storage/innobase/row/row0merge.cc6
-rw-r--r--storage/innobase/row/row0sel.cc85
7 files changed, 127 insertions, 33 deletions
diff --git a/storage/innobase/api/api0api.cc b/storage/innobase/api/api0api.cc
index 739ea9f7572..711714861ab 100644
--- a/storage/innobase/api/api0api.cc
+++ b/storage/innobase/api/api0api.cc
@@ -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
@@ -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));
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index e77c9bb4caf..526836646d2 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -8839,6 +8839,27 @@ ha_innobase::ft_init_ext(
}
/*****************************************************************//**
+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
once the search result (Doc IDs) is available */
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 46d689ce1e8..f9e98d5dfe6 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -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.
Copyright (c) 2013, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -143,6 +143,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);
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index f5f159fc414..043417333ab 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -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
@@ -724,6 +724,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 */
@@ -874,6 +876,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.*/
diff --git a/storage/innobase/include/row0sel.h b/storage/innobase/include/row0sel.h
index fd5bc755a22..afeb216c2a2 100644
--- a/storage/innobase/include/row0sel.h
+++ b/storage/innobase/include/row0sel.h
@@ -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
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index ba2f80185bf..3976f31fe12 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -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.
Copyright (c) 2014, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -1452,6 +1452,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)) {
@@ -1875,8 +1877,6 @@ write_buffers:
if (err != DB_SUCCESS) {
goto func_exit;
}
-
- mem_heap_empty(row_heap);
}
func_exit:
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 9bf8e1975fd..505de35840f 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -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
@@ -2556,34 +2556,32 @@ row_sel_store_row_id_to_prebuilt(
row_sel_field_store_in_mysql_format_func(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 */
+ const byte* data,
+ ulint len)
{
byte* ptr;
#ifdef UNIV_DEBUG
@@ -3330,6 +3328,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
@@ -4969,8 +4997,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);
}
}