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