1/*****************************************************************************
2
3Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License as published by the Free Software
7Foundation; version 2 of the License.
8
9This program is distributed in the hope that it will be useful, but WITHOUT
10ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13You should have received a copy of the GNU General Public License along with
14this program; if not, write to the Free Software Foundation, Inc.,
1551 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16
17*****************************************************************************/
18
19/**************************************************//**
20@file row/row0ext.cc
21Caching of externally stored column prefixes
22
23Created September 2006 Marko Makela
24*******************************************************/
25
26#include "row0ext.h"
27#include "btr0cur.h"
28
29/** Fills the column prefix cache of an externally stored column.
30@param[in,out] ext column prefix cache
31@param[in] i index of ext->ext[]
32@param[in] page_size page size
33@param[in] dfield data field */
34static
35void
36row_ext_cache_fill(
37 row_ext_t* ext,
38 ulint i,
39 const page_size_t& page_size,
40 const dfield_t* dfield)
41{
42 const byte* field = static_cast<const byte*>(
43 dfield_get_data(dfield));
44 ulint f_len = dfield_get_len(dfield);
45 byte* buf = ext->buf + i * ext->max_len;
46
47 ut_ad(ext->max_len > 0);
48 ut_ad(i < ext->n_ext);
49 ut_ad(dfield_is_ext(dfield));
50 ut_a(f_len >= BTR_EXTERN_FIELD_REF_SIZE);
51
52 if (UNIV_UNLIKELY(!memcmp(field_ref_zero,
53 field + f_len - BTR_EXTERN_FIELD_REF_SIZE,
54 BTR_EXTERN_FIELD_REF_SIZE))) {
55 /* The BLOB pointer is not set: we cannot fetch it */
56 ext->len[i] = 0;
57 } else {
58 if (ext->max_len == REC_VERSION_56_MAX_INDEX_COL_LEN
59 && f_len > BTR_EXTERN_FIELD_REF_SIZE) {
60 /* In this case, the field is in B format or beyond,
61 (refer to the definition of row_ext_t.max_len)
62 and the field is already fill with prefix, otherwise
63 f_len would be BTR_EXTERN_FIELD_REF_SIZE.
64 So there is no need to re-read the prefix externally,
65 but just copy the local prefix to buf. Please note
66 if the ext->len[i] is zero, it means an error
67 as above. */
68 memcpy(buf, field, f_len - BTR_EXTERN_FIELD_REF_SIZE);
69 ext->len[i] = f_len - BTR_EXTERN_FIELD_REF_SIZE;
70 } else {
71 /* Fetch at most ext->max_len of the column.
72 The column should be non-empty. However,
73 trx_rollback_all_recovered() may try to
74 access a half-deleted BLOB if the server previously
75 crashed during the execution of
76 btr_free_externally_stored_field(). */
77 ext->len[i] = btr_copy_externally_stored_field_prefix(
78 buf, ext->max_len, page_size, field, f_len);
79 }
80 }
81}
82
83/********************************************************************//**
84Creates a cache of column prefixes of externally stored columns.
85@return own: column prefix cache */
86row_ext_t*
87row_ext_create(
88/*===========*/
89 ulint n_ext, /*!< in: number of externally stored columns */
90 const ulint* ext, /*!< in: col_no's of externally stored columns
91 in the InnoDB table object, as reported by
92 dict_col_get_no(); NOT relative to the records
93 in the clustered index */
94 ulint flags, /*!< in: table->flags */
95 const dtuple_t* tuple, /*!< in: data tuple containing the field
96 references of the externally stored
97 columns; must be indexed by col_no;
98 the clustered index record must be
99 covered by a lock or a page latch
100 to prevent deletion (rollback or purge). */
101 mem_heap_t* heap) /*!< in: heap where created */
102{
103 ulint i;
104 const page_size_t& page_size = dict_tf_get_page_size(flags);
105
106 row_ext_t* ret;
107
108 ut_ad(n_ext > 0);
109
110 ret = static_cast<row_ext_t*>(
111 mem_heap_alloc(heap,
112 (sizeof *ret) + (n_ext - 1) * sizeof ret->len));
113
114 ret->n_ext = n_ext;
115 ret->ext = ext;
116 ret->max_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags);
117 ret->page_size.copy_from(page_size);
118
119 ret->buf = static_cast<byte*>(
120 mem_heap_alloc(heap, n_ext * ret->max_len));
121
122#ifdef UNIV_DEBUG
123 memset(ret->buf, 0xaa, n_ext * ret->max_len);
124 UNIV_MEM_ALLOC(ret->buf, n_ext * ret->max_len);
125#endif
126
127 /* Fetch the BLOB prefixes */
128 for (i = 0; i < n_ext; i++) {
129 const dfield_t* dfield;
130
131 dfield = dtuple_get_nth_field(tuple, ext[i]);
132 row_ext_cache_fill(ret, i, page_size, dfield);
133 }
134
135 return(ret);
136}
137