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