MySQL 9.0.0
Source Code Documentation
column.h
Go to the documentation of this file.
1/* Copyright (c) 2016, 2024, Oracle and/or its affiliates.
2
3This program is free software; you can redistribute it and/or modify it under
4the terms of the GNU General Public License, version 2.0, as published by the
5Free Software Foundation.
6
7This program is designed to work with certain software (including
8but not limited to OpenSSL) that is licensed under separate terms,
9as designated in a particular file or component or in included license
10documentation. The authors of MySQL hereby grant you an additional
11permission to link the program and your derivative works with the
12separately licensed software that they have either included with
13the program or referenced in the documentation.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
18for more details.
19
20You should have received a copy of the GNU General Public License along with
21this program; if not, write to the Free Software Foundation, Inc.,
2251 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24/** @file storage/temptable/include/temptable/column.h
25TempTable Column declaration. */
26
27#ifndef TEMPTABLE_COLUMN_H
28#define TEMPTABLE_COLUMN_H
29
30#include <cstddef>
31#include <vector>
32
33#include "my_dbug.h"
34#include "sql/field.h"
37
38namespace temptable {
39
40/** A column class that describes the metadata of a column. */
41class Column {
42 public:
43 /** Constructor. */
44 Column(
45 /** [in] A pointer to the row (user data). */
46 const unsigned char *mysql_row,
47 /** [in] MySQL table that contains the column. */
48 const TABLE &mysql_table TEMPTABLE_UNUSED_NODBUG,
49 /** [in] MySQL field (column/cell) that describes the columns. */
50 const Field &mysql_field);
51
52 /** Check if a particular cell is NULL. The cell is the intersection of this
53 * column with the provided row (in MySQL write_row() format).
54 * @return true if the cell is NULL */
55 bool read_is_null(
56 /** [in] MySQL row that contains the cell to be checked. */
57 const unsigned char *mysql_row) const;
58
59 /** Write the information that cell is NULL or not. */
60 void write_is_null(
61 /** [in] True if cell is NULL, false if it has value. */
62 bool is_null,
63 /** [out] MySQL row buffer to write data into. */
64 unsigned char *mysql_row,
65 /** [in] Length of the row buffer. */
66 size_t mysql_row_length) const;
67
68 /** In MySQL write_row() format - the length of the actual user data of a cell
69 * in a given row.
70 * @return user data length of the cell that corresponds to this column in the
71 * given row */
72 uint32_t read_user_data_length(
73 /** [in] MySQL row buffer to read data from. */
74 const unsigned char *mysql_row) const;
75
76 /** Write the length of user data stored in a cell. */
78 /** [in] User data length. */
79 uint32_t data_length,
80 /** [out] MySQL row buffer to write data into. */
81 unsigned char *mysql_row,
82 /** [in] Length of the row buffer. */
83 size_t mysql_row_length) const;
84
85 /** Return pointer to user data in MySQL row.
86 * @return Pointer to user data. */
87 const unsigned char *get_user_data_ptr(const unsigned char *mysql_row) const;
88
89 /** Reads user data stored in a cell.
90 * Cannot be used for columns stored as BLOBs.
91 * Performs a deep copy of the data. */
92 void read_user_data(
93 /** [out] Pointer to store user data. */
94 unsigned char *data,
95 /** [out] Length of the data to read. */
96 uint32_t data_length,
97 /** [in] MySQL row buffer to read data from. */
98 const unsigned char *mysql_row,
99 /** [in] Length of the row buffer. */
100 size_t mysql_row_length) const;
101
102 /** Write user data stored in a cell.
103 * Cannot be used for columns stored as blobs. */
104 void write_user_data(
105 /** [in] True if cell is NULL, false if it has value. */
106 bool is_null,
107 /** [in] Pointer to used data. */
108 const unsigned char *data,
109 /** [in] Length of user data. */
110 uint32_t data_length,
111 /** [out] MySQL row buffer to write data into. */
112 unsigned char *mysql_row,
113 /** [in] Length of the row buffer. */
114 size_t mysql_row_length) const;
115
116 private:
117 /** Check if the cells in this column can be NULL.
118 * @return true if cells are allowed to be NULL. */
119 bool is_nullable() const;
120
121 /** Check this column stores blobs.
122 * @return true if it is a blob column. */
123 bool is_blob() const;
124
125 /** Check if different cells that belong to this column can have different
126 * size (eg VARCHAR).
127 * @return true if all cells are the same size */
128 bool is_fixed_size() const;
129
130 /** Reads user data stored in a cell.
131 * Cannot be used for columns stored as BLOBs.
132 * Performs a deep copy of the data. */
134 /** [out] Pointer to store user data. */
135 unsigned char *data,
136 /** [out] Length of the data to read. */
137 uint32_t data_length,
138 /** [in] MySQL row buffer to read data from. */
139 const unsigned char *mysql_row,
140 /** [in] Length of the row buffer. */
141 size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const;
142
143 /** Write user data stored in a cell.
144 * Cannot be used for columns stored as blobs. */
146 /** [in] Pointer to used data. */
147 const unsigned char *data,
148 /** [in] Length of user data. */
149 uint32_t data_length,
150 /** [out] MySQL row buffer to write data into. */
151 unsigned char *mysql_row,
152 /** [in] Length of the row buffer. */
153 size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const;
154
155 /** Reads user data stored in a cell for columns stored as BLOBs.
156 * Performs a deep copy of the data. */
158 /** [out] Pointer to store user data. */
159 unsigned char *data,
160 /** [out] Length of the data to read. */
161 uint32_t data_length,
162 /** [in] MySQL row buffer to read data from. */
163 const unsigned char *mysql_row,
164 /** [in] Length of the row buffer. */
165 size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const;
166
167 /** Write user data stored in a cell for columns stored as BLOBs.
168 * NOTE: Currently only pointer is stored, no data is copied and the
169 * length is ignored. */
171 /** [in] Pointer to user data. Can be NULL for cells with NULL value. */
172 const unsigned char *data,
173 /** [in] Length of user data. */
174 uint32_t data_length,
175 /** [out] MySQL row buffer to write data into. */
176 unsigned char *mysql_row,
177 /** [in] Length of the row buffer. */
178 size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const;
179
180 /** Calculate pointer to user data in a MySQL row.
181 * Cannot be used for columns stored as BLOBs.
182 * @return Pointer to user data stored in a cell. */
183 const unsigned char *calculate_user_data_ptr(
184 /** [in] MySQL row buffer that stores the user data. */
185 const unsigned char *mysql_row) const;
186
187 /** Reads pointer to user data for a column stored as BLOB.
188 * @return Pointer to user data stored in a BLOB field. */
189 const unsigned char *read_blob_data_ptr(
190 /** [in] MySQL row buffer that stores BLOB data pointer. */
191 const unsigned char *mysql_row) const;
192
193 /** True if can be NULL. */
195
196 /** True if it is a blob. */
198
199 /** Bitmask to extract is is-NULL bit from the is-NULL byte. */
201
202 /** The number of bytes that indicate the length of the user data in the
203 * cell, for variable sized cells. If this is 0, then the cell is fixed
204 * size. */
206
207 union {
208 /** Length of the user data of a cell.
209 * It is for fixed size cells (when `m_length_bytes_size == 0`). */
210 uint32_t m_length;
211
212 /** Offset of the bytes that indicate the user data length of a cell.
213 * It is used for variable size cells (when `m_length_bytes_size > 0`). */
214 uint32_t m_offset;
215 };
216
217 /** The offset of the is-NULL byte from the start of the mysql row. If
218 * `m_null_bitmask` is set in this byte and `m_nullable` is true, then that
219 * particular cell is NULL. */
221
222 /** The offset of the user data from the start of the mysql row in bytes. */
224};
225
226/** A type that designates all the columns of a table. */
227typedef std::vector<Column, Allocator<Column>> Columns;
228
229/* Implementation of inlined methods. */
230
231inline bool Column::is_nullable() const { return m_nullable; }
232
233inline bool Column::is_blob() const { return m_is_blob; }
234
235inline bool Column::read_is_null(const unsigned char *mysql_row) const {
236 return m_nullable && (m_null_bitmask & *(mysql_row + m_null_byte_offset));
237}
238
239inline void Column::write_is_null(bool is_null, unsigned char *mysql_row,
240 size_t mysql_row_length
242 if (is_nullable()) {
243 unsigned char *b = mysql_row + m_null_byte_offset;
244
245 assert(buf_is_inside_another(b, 1, mysql_row, mysql_row_length));
246
247 if (is_null) {
248 *b |= m_null_bitmask;
249 } else {
250 *b &= ~m_null_bitmask;
251 }
252 } else {
253 assert(!is_null);
254 }
255}
256
257inline bool Column::is_fixed_size() const { return m_length_bytes_size == 0; }
258
260 const unsigned char *mysql_row) const {
261 if (m_length_bytes_size == 0) {
262 /* Fixed size cell. */
263 return m_length;
264 }
265
266 // data_length may contain junk value while particular cell is NULL
267 if (read_is_null(mysql_row)) {
268 return 0;
269 }
270
271 const unsigned char *p = mysql_row + m_offset;
272 switch (m_length_bytes_size) {
273 case 1:
274 return *p;
275 case 2:
276 return *p | (*(p + 1) << 8);
277 case 3:
278 return *p | (*(p + 1) << 8) | (*(p + 2) << 16);
279 case 4:
280 return *p | (*(p + 1) << 8) | (*(p + 2) << 16) | (*(p + 3) << 24);
281 }
282
283 my_abort();
284 return 0;
285}
286
288 uint32_t data_length, unsigned char *mysql_row,
289 size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const {
290 unsigned char *p = mysql_row + m_offset;
291
292 assert((m_length_bytes_size == 0) ||
294 mysql_row_length)));
295
296 switch (m_length_bytes_size) {
297 case 0:
298 /* Fixed size cell. */
299 break;
300 case 1:
301 assert(data_length <= 0xFF);
302 p[0] = data_length;
303 break;
304 case 2:
305 assert(data_length <= 0xFFFF);
306 p[0] = (data_length & 0x000000FF);
307 p[1] = (data_length & 0x0000FF00) >> 8;
308 break;
309 case 3:
310 assert(data_length <= 0xFFFFFF);
311 p[0] = (data_length & 0x000000FF);
312 p[1] = (data_length & 0x0000FF00) >> 8;
313 p[2] = (data_length & 0x00FF0000) >> 16;
314 break;
315 case 4:
316 /* assert(data_length <= 0xFFFFFFFF). */
317 p[0] = (data_length & 0x000000FF);
318 p[1] = (data_length & 0x0000FF00) >> 8;
319 p[2] = (data_length & 0x00FF0000) >> 16;
320 p[3] = (data_length & 0xFF000000) >> 24;
321 break;
322 default:
323 DBUG_ABORT();
324 }
325}
326
327inline void Column::read_user_data(unsigned char *data, uint32_t data_length,
328 const unsigned char *mysql_row,
329 size_t mysql_row_length) const {
330 if (is_blob()) {
331 read_blob_user_data(data, data_length, mysql_row, mysql_row_length);
332 } else {
333 read_std_user_data(data, data_length, mysql_row, mysql_row_length);
334 }
335}
336
337inline void Column::write_user_data(bool is_null, const unsigned char *data,
338 uint32_t data_length,
339 unsigned char *mysql_row,
340 size_t mysql_row_length) const {
341 if (is_blob()) {
342 if (is_null) {
343 write_blob_user_data(nullptr, 0, mysql_row, mysql_row_length);
344 } else {
345 assert(data);
346 write_blob_user_data(data, data_length, mysql_row, mysql_row_length);
347 }
348 } else {
349 write_std_user_data(data, data_length, mysql_row, mysql_row_length);
350 }
351}
352
354 unsigned char *data, uint32_t data_length, const unsigned char *mysql_row,
355 size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const {
356 assert(!is_blob());
357
358 const unsigned char *p = mysql_row + m_user_data_offset;
359
360 assert(buf_is_inside_another(p, data_length, mysql_row, mysql_row_length));
361
362 memcpy(data, p, data_length);
363}
364
366 const unsigned char *data, uint32_t data_length, unsigned char *mysql_row,
367 size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const {
368 assert(!is_blob());
369
370 if (data_length > 0) {
371 unsigned char *p = mysql_row + m_user_data_offset;
372
373 assert(buf_is_inside_another(p, data_length, mysql_row, mysql_row_length));
374
375 memcpy(p, data, data_length);
376 }
377}
378
380 unsigned char *data, uint32_t data_length, const unsigned char *mysql_row,
381 size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const {
382 assert(is_blob());
383
384 const unsigned char *p = mysql_row + m_user_data_offset;
385
386 const unsigned char *ptr_to_data;
387
388 assert(buf_is_inside_another(p, sizeof(ptr_to_data), mysql_row,
389 mysql_row_length));
390
391 /* read the address */
392 memcpy(&ptr_to_data, p, sizeof(ptr_to_data));
393
394 assert((ptr_to_data) || (data_length == 0));
395
396 memcpy(data, ptr_to_data, data_length);
397}
398
400 const unsigned char *data, uint32_t data_length TEMPTABLE_UNUSED,
401 unsigned char *mysql_row,
402 size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const {
403 assert(is_blob());
404
405 unsigned char *p = mysql_row + m_user_data_offset;
406
407 /* Note1: data could be NULL.
408 * Note2: shallow copy - pointer to original data is stored. */
409 const unsigned char *ptr_to_data = data;
410
411 assert(buf_is_inside_another(p, sizeof(ptr_to_data), mysql_row,
412 mysql_row_length));
413
414 memcpy(p, &ptr_to_data, sizeof(ptr_to_data));
415}
416
417inline const unsigned char *Column::get_user_data_ptr(
418 const unsigned char *mysql_row) const {
419 if (is_blob()) {
420 return read_blob_data_ptr(mysql_row);
421 } else {
422 return calculate_user_data_ptr(mysql_row);
423 }
424}
425
426inline const unsigned char *Column::calculate_user_data_ptr(
427 const unsigned char *mysql_row) const {
428 assert(!is_blob());
429
430 return (mysql_row + m_user_data_offset);
431}
432
433inline const unsigned char *Column::read_blob_data_ptr(
434 const unsigned char *mysql_row) const {
435 assert(is_blob());
436
437 const unsigned char *p = mysql_row + m_user_data_offset;
438
439 const unsigned char *data_ptr;
440
441 /* read the address */
442 memcpy(&data_ptr, p, sizeof(data_ptr));
443
444 return data_ptr;
445}
446
447} /* namespace temptable */
448
449#endif /* TEMPTABLE_COLUMN_H */
Definition: field.h:577
A column class that describes the metadata of a column.
Definition: column.h:41
bool m_is_blob
True if it is a blob.
Definition: column.h:197
uint32_t m_user_data_offset
The offset of the user data from the start of the mysql row in bytes.
Definition: column.h:223
void write_blob_user_data(const unsigned char *data, uint32_t data_length, unsigned char *mysql_row, size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const
Write user data stored in a cell for columns stored as BLOBs.
Definition: column.h:399
bool m_nullable
True if can be NULL.
Definition: column.h:194
uint8_t m_length_bytes_size
The number of bytes that indicate the length of the user data in the cell, for variable sized cells.
Definition: column.h:205
void write_user_data_length(uint32_t data_length, unsigned char *mysql_row, size_t mysql_row_length) const
Write the length of user data stored in a cell.
Definition: column.h:287
bool is_nullable() const
Check if the cells in this column can be NULL.
Definition: column.h:231
void write_std_user_data(const unsigned char *data, uint32_t data_length, unsigned char *mysql_row, size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const
Write user data stored in a cell.
Definition: column.h:365
bool is_blob() const
Check this column stores blobs.
Definition: column.h:233
const unsigned char * calculate_user_data_ptr(const unsigned char *mysql_row) const
Calculate pointer to user data in a MySQL row.
Definition: column.h:426
void read_blob_user_data(unsigned char *data, uint32_t data_length, const unsigned char *mysql_row, size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const
Reads user data stored in a cell for columns stored as BLOBs.
Definition: column.h:379
bool read_is_null(const unsigned char *mysql_row) const
Check if a particular cell is NULL.
Definition: column.h:235
uint8_t m_null_bitmask
Bitmask to extract is is-NULL bit from the is-NULL byte.
Definition: column.h:200
uint32_t m_length
Length of the user data of a cell.
Definition: column.h:210
uint32_t read_user_data_length(const unsigned char *mysql_row) const
In MySQL write_row() format - the length of the actual user data of a cell in a given row.
Definition: column.h:259
uint32_t m_offset
Offset of the bytes that indicate the user data length of a cell.
Definition: column.h:214
uint32_t m_null_byte_offset
The offset of the is-NULL byte from the start of the mysql row.
Definition: column.h:220
bool is_fixed_size() const
Check if different cells that belong to this column can have different size (eg VARCHAR).
Definition: column.h:257
void read_std_user_data(unsigned char *data, uint32_t data_length, const unsigned char *mysql_row, size_t mysql_row_length TEMPTABLE_UNUSED_NODBUG) const
Reads user data stored in a cell.
Definition: column.h:353
Column(const unsigned char *mysql_row, const TABLE &mysql_table TEMPTABLE_UNUSED_NODBUG, const Field &mysql_field)
Constructor.
Definition: column.cc:39
void write_is_null(bool is_null, unsigned char *mysql_row, size_t mysql_row_length) const
Write the information that cell is NULL or not.
Definition: column.h:239
const unsigned char * read_blob_data_ptr(const unsigned char *mysql_row) const
Reads pointer to user data for a column stored as BLOB.
Definition: column.h:433
void write_user_data(bool is_null, const unsigned char *data, uint32_t data_length, unsigned char *mysql_row, size_t mysql_row_length) const
Write user data stored in a cell.
Definition: column.h:337
const unsigned char * get_user_data_ptr(const unsigned char *mysql_row) const
Return pointer to user data in MySQL row.
Definition: column.h:417
void read_user_data(unsigned char *data, uint32_t data_length, const unsigned char *mysql_row, size_t mysql_row_length) const
Reads user data stored in a cell.
Definition: column.h:327
const char * p
Definition: ctype-mb.cc:1225
TempTable miscellaneous helper utilities declarations.
#define TEMPTABLE_UNUSED_NODBUG
Definition: misc.h:39
#define TEMPTABLE_UNUSED
Definition: misc.h:34
void my_abort()
Calls our own implementation of abort, if specified, or std's abort().
Definition: my_init.cc:261
#define DBUG_ABORT()
Definition: my_dbug.h:202
Definition: allocator.h:45
std::vector< Column, Allocator< Column > > Columns
A type that designates all the columns of a table.
Definition: column.h:227
bool buf_is_inside_another(const unsigned char *small, size_t small_length, const unsigned char *big, size_t big_length)
Check if a given buffer is inside another buffer.
Definition: misc.h:46
TempTable custom allocator.
Definition: table.h:1407