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