MySQL 9.1.0
Source Code Documentation
row.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/row.h
25TempTable Row declarations. */
26
27// clang-format off
28/** @page PAGE_TEMPTABLE_ROW_FORMAT Row format
29
30The handler interface uses two different formats. Assume the following table:
31
32~~~~~~~~~~~~~{.sql}
33CREATE TABLE tt (
34 c1 INT(11) DEFAULT NULL,
35 c2 INT(11) NOT NULL,
36 c3 VARCHAR(8) DEFAULT NULL,
37 c4 VARCHAR(8) NOT NULL,
38 c5 CHAR(8) DEFAULT NULL,
39 c6 CHAR(8) NOT NULL,
40 c7 VARCHAR(300) DEFAULT NULL,
41 KEY `i1` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`)
42);
43~~~~~~~~~~~~~
44
45@section WRITE_ROW_FORMAT write_row() format
46
47This format is used in the input of the `write_row()` method. The same format
48is used by the storage engine in the output buffers of `rnd_next()` and
49`index_read()`. Consider the following INSERT statement:
50
51~~~~~~~~~~~~~{.sql}
52INSERT INTO t VALUES (123, 123, 'abcd', 'abcd', 'abcd', 'abcd', 'abcd');
53~~~~~~~~~~~~~
54
55the row buffer that is passed to `write_row()` is 352 bytes:
56
57hex | raw | description
58--- | --- | -----------
59f0 | . | NULLs bitmask 11110000 denoting that out of 4 columns that could possibly be NULL (c1, c3, c5 and c7) none is actually NULL.
607b | { | c1=123 stored in 4 bytes (little endian) (1/4)
6100 | . | from above (2/4)
6200 | . | from above (3/4)
6300 | . | from above (4/4)
647b | { | c2=123 stored in 4 bytes (little endian) (1/4)
6500 | . | from above (2/4)
6600 | . | from above (3/4)
6700 | . | from above (4/4)
6804 | . | the length of the following data (for VARCHAR cells): 4
6961 | a | c3='abcd' - the actual data (1/4)
7062 | b | from above (2/4)
7163 | c | from above (3/4)
7264 | d | from above (4/4)
73a5 | . | 4 wasted bytes for c3 (1/4)
74a5 | . | from above (2/4)
75a5 | . | from above (3/4)
76a5 | . | from above (4/4)
7704 | . | the length of the following data (for VARCHAR cells): 4
7861 | a | c4='abcd' - the actual data (1/4)
7962 | b | from above (2/4)
8063 | c | from above (3/4)
8164 | d | from above (4/4)
82a5 | . | 4 wasted bytes for c4 (1/4)
83a5 | . | from above (2/4)
84a5 | . | from above (3/4)
85a5 | . | from above (4/4)
8661 | a | c5='abcd ' (padded to 8 bytes with spaces at the end) (1/8)
8762 | b | from above (2/8)
8863 | c | from above (3/8)
8964 | d | from above (4/8)
9020 | | from above (5/8)
9120 | | from above (6/8)
9220 | | from above (7/8)
9320 | | from above (8/8)
9461 | a | c6='abcd ' (padded to 8 bytes with spaces at the end) (1/8)
9562 | b | from above (2/8)
9663 | c | from above (3/8)
9764 | d | from above (4/8)
9820 | | from above (5/8)
9920 | | from above (6/8)
10020 | | from above (7/8)
10120 | | from above (8/8)
10204 | . | the length (occupying 2 bytes) of the following data (for VARCHAR cells): 4 (1/2)
10300 | . | from above (2/2)
10461 | a | c7='abcd' - the actual data (1/4)
10562 | b | from above (2/4)
10663 | c | from above (3/4)
10764 | d | from above (4/4)
108a5 | . | a5 repeats 296 times, wasted bytes for c7 (1/296)
109a5 | . | from above (2/296)
110.. | .. | ..
111a5 | . | from above (296/296)
112
113@section INDEX_READ_FORMAT index_read() format
114
115Consider the following SELECT statement:
116
117~~~~~~~~~~~~~{.sql}
118SELECT * FROM t WHERE
119c1=123 AND
120c2=123 AND
121c3='abcd' AND
122c4='abcd' AND
123c5='abcd' AND
124c6='abcd' AND
125c7='abcd';
126~~~~~~~~~~~~~
127
128the indexed cells buffer that is passed to `index_read()` is 350 bytes:
129
130hex | raw | description
131--- | --- | -----------
13200 | . | c1 NULL byte, denoting that c1 is not NULL (would have been 01 is c1 was NULL)
1337b | { | c1=123 stored in 4 bytes (little endian) (1/4)
13400 | . | from above (2/4)
13500 | . | from above (3/4)
13600 | . | from above (4/4)
1377b | { | c2=123 stored in 4 bytes (little endian) (because c2 cannot be NULL there is no leading byte to indicate NULL or not NULL) (1/4)
13800 | . | from above (2/4)
13900 | . | from above (3/4)
14000 | . | from above (4/4)
14100 | . | c3 NULL byte, denoting that c3 is not NULL (would have been 01 if c3 was NULL)
14204 | . | c3 length (4), always 2 bytes (1/2)
14300 | . | from above (2/2)
14461 | a | c3='abcd' - the actual data (1/4)
14562 | b | from above (2/4)
14663 | c | from above (3/4)
14764 | d | from above (4/4)
14800 | . | 4 wasted bytes for c3 (1/4)
14900 | . | from above (2/4)
15000 | . | from above (3/4)
15100 | . | from above (4/4)
15204 | . | c4 length (4), always 2 bytes (no NULL byte for c4) (1/2)
15300 | . | from above (2/2)
15461 | a | c4='abcd' - the actual data (1/4)
15562 | b | from above (2/4)
15663 | c | from above (3/4)
15764 | d | from above (4/4)
15800 | . | 4 wasted bytes for c4 (1/4)
15900 | . | from above (2/4)
16000 | . | from above (3/4)
16100 | . | from above (4/4)
16200 | . | c5 NULL byte, denoting that c5 is not NULL (would have been 01 if c5 was NULL)
16361 | a | c5='abcd ' (1/8)
16462 | b | from above (2/8)
16563 | c | from above (3/8)
16664 | d | from above (4/8)
16720 | | from above (5/8)
16820 | | from above (6/8)
16920 | | from above (7/8)
17020 | | from above (8/8)
17161 | a | c6='abcd ' (c6 cannot be NULL) (1/8)
17262 | b | from above (2/8)
17363 | c | from above (3/8)
17464 | d | from above (4/8)
17520 | | from above (5/8)
17620 | | from above (6/8)
17720 | | from above (7/8)
17820 | | from above (8/8)
17900 | . | c7 NULL byte
18004 | . | c7 length (4), always 2 bytes (1/2)
18100 | . | from above (2/2)
18261 | a | c7='abcd' - the actual data (1/4)
18362 | b | from above (2/4)
18463 | c | from above (3/4)
18564 | d | from above (4/4)
18600 | . | 296 wasted bytes for c7 (1/296)
18700 | . | from above (2/296)
188.. | .. | ..
18900 | . | from above (296/296)
190
191@section TEMPTABLE_FORMAT TempTable format
192
193We introduce a new format, lets call it TempTable format, that fulfills the
194following:
195
1961. Does not waste space for VARCHAR cells
1972. It must be possible to convert from write_row() format to this new format
1983. It must be possible to convert the new format to write_row() format
1994. When a row is stored internally in this new format, it must be possible
200 to compare its relevant cells to cells in the index_read() format without
201 any heap memory allocation (malloc()/new) and without copying of user
202 data (memcpy()).
203
204For this we introduce a Cell class, which has the following properties:
2051. NULL byte (bool, 1 byte)
2062. user data length (uint32_t, 4 bytes)
2073. pointer to the user data (void*, 8 bytes on 64-bit machines)
2084. can compare itself to another cell
2095. can hash itself
210
211A Cell object does not store actual user data, only a pointer to it. This way
212we can create cells that point inside the buffer provided to `write_row()` or
213point inside our own buffer, where the user data is copied for storage.
214
215A row in the TempTable format consists of a set of Cells stored in one buffer,
216together with the actual user data. The size of a row is the size of all
217user data + 16 bytes overhead for each cell (for the Cell object).
218
219In the above example both the row (`write_row()` format) and the indexed cells
220(`index_read()` format) would be represented like in the table below, in 148
221bytes. Think of a POD
222~~~~~~~~~~~~~{.cpp}
223struct Cell {
224 bool is_null;
225 uint32_t len;
226 void* data;
227};
228~~~~~~~~~~~~~
229
230hex | raw | description
231--- | --- | -----------
23200 | . | c1 NULL byte (00 means not NULL)
23300 | . | 3 bytes padding (1/3)
23400 | . | from above (2/3)
23500 | . | from above (3/3)
23600 | . | c1 length in 4 bytes in whatever is the machine's native byte order (1/4)
23700 | . | from above (2/4)
23800 | . | from above (3/4)
23904 | . | from above (4/4)
240f1 | . | address in memory where c1 user data is stored (1/8)
241f1 | . | from above (2/8)
242f1 | . | from above (3/8)
243f1 | . | from above (4/8)
244f1 | . | from above (5/8)
245f1 | . | from above (6/8)
246f1 | . | from above (7/8)
247f1 | . | from above (8/8)
24800 | . | c2 NULL byte (00 means not NULL)
24900 | . | 3 bytes padding (1/3)
25000 | . | from above (2/3)
25100 | . | from above (3/3)
25200 | . | c2 length in 4 bytes in whatever is the machine's native byte order (1/4)
25300 | . | from above (2/4)
25400 | . | from above (3/4)
25504 | . | from above (4/4)
256f2 | . | address in memory where c2 user data is stored (1/8)
257f2 | . | from above (2/8)
258f2 | . | from above (3/8)
259f2 | . | from above (4/8)
260f2 | . | from above (5/8)
261f2 | . | from above (6/8)
262f2 | . | from above (7/8)
263f2 | . | from above (8/8)
26400 | . | c3 NULL byte (00 means not NULL)
26500 | . | 3 bytes padding (1/3)
26600 | . | from above (2/3)
26700 | . | from above (3/3)
26800 | . | c3 length in 4 bytes in whatever is the machine's native byte order (1/4)
26900 | . | from above (2/4)
27000 | . | from above (3/4)
27104 | . | from above (4/4)
272f3 | . | address in memory where c3 user data is stored (1/8)
273f3 | . | from above (2/8)
274f3 | . | from above (3/8)
275f3 | . | from above (4/8)
276f3 | . | from above (5/8)
277f3 | . | from above (6/8)
278f3 | . | from above (7/8)
279f3 | . | from above (8/8)
28000 | . | c4 NULL byte (00 means not NULL)
28100 | . | 3 bytes padding (1/3)
28200 | . | from above (2/3)
28300 | . | from above (3/3)
28400 | . | c4 length in 4 bytes in whatever is the machine's native byte order (1/4)
28500 | . | from above (2/4)
28600 | . | from above (3/4)
28704 | . | from above (4/4)
288f4 | . | address in memory where c4 user data is stored (1/8)
289f4 | . | from above (2/8)
290f4 | . | from above (3/8)
291f4 | . | from above (4/8)
292f4 | . | from above (5/8)
293f4 | . | from above (6/8)
294f4 | . | from above (7/8)
295f4 | . | from above (8/8)
29600 | . | c5 NULL byte (00 means not NULL)
29700 | . | 3 bytes padding (1/3)
29800 | . | from above (2/3)
29900 | . | from above (3/3)
30000 | . | c5 length in 4 bytes in whatever is the machine's native byte order (1/4)
30100 | . | from above (2/4)
30200 | . | from above (3/4)
30308 | . | from above (4/4)
304f5 | . | address in memory where c5 user data is stored (1/8)
305f5 | . | from above (2/8)
306f5 | . | from above (3/8)
307f5 | . | from above (4/8)
308f5 | . | from above (5/8)
309f5 | . | from above (6/8)
310f5 | . | from above (7/8)
311f5 | . | from above (8/8)
31200 | . | c6 NULL byte (00 means not NULL)
31300 | . | 3 bytes padding (1/3)
31400 | . | from above (2/3)
31500 | . | from above (3/3)
31600 | . | c6 length in 4 bytes in whatever is the machine's native byte order (1/4)
31700 | . | from above (2/4)
31800 | . | from above (3/4)
31908 | . | from above (4/4)
320f6 | . | address in memory where c6 user data is stored (1/8)
321f6 | . | from above (2/8)
322f6 | . | from above (3/8)
323f6 | . | from above (4/8)
324f6 | . | from above (5/8)
325f6 | . | from above (6/8)
326f6 | . | from above (7/8)
327f6 | . | from above (8/8)
32800 | . | c7 NULL byte (00 means not NULL)
32900 | . | 3 bytes padding (1/3)
33000 | . | from above (2/3)
33100 | . | from above (3/3)
33200 | . | c7 length in 4 bytes in whatever is the machine's native byte order (1/4)
33300 | . | from above (2/4)
33400 | . | from above (3/4)
33504 | . | from above (4/4)
336f7 | . | address in memory where c7 user data is stored (1/8)
337f7 | . | from above (2/8)
338f7 | . | from above (3/8)
339f7 | . | from above (4/8)
340f7 | . | from above (5/8)
341f7 | . | from above (6/8)
342f7 | . | from above (7/8)
343f7 | . | from above (8/8)
3447b | { | c1=123, the address of this is f1f1f1f1 (1/4)
34500 | . | from above (2/4)
34600 | . | from above (3/4)
34700 | . | from above (4/4)
3487b | { | c2=123, the address of this is f2f2f2f2 (1/4)
34900 | . | from above (2/4)
35000 | . | from above (3/4)
35100 | . | from above (4/4)
35261 | a | c3='abcd', the address of this is f3f3f3f3 (1/4)
35362 | b | from above (2/4)
35463 | c | from above (3/4)
35564 | d | from above (4/4)
35661 | a | c4='abcd', the address of this is f4f4f4f4 (1/4)
35762 | b | from above (2/4)
35863 | c | from above (3/4)
35964 | d | from above (4/4)
36061 | a | c5='abcd ', the address of this is f5f5f5f5 (1/8)
36162 | b | from above (2/8)
36263 | c | from above (3/8)
36364 | d | from above (4/8)
36420 | | from above (5/8)
36520 | | from above (6/8)
36620 | | from above (7/8)
36720 | | from above (8/8)
36861 | a | c6='abcd ', the address of this is f6f6f6f6 (1/8)
36962 | b | from above (2/8)
37063 | c | from above (3/8)
37164 | d | from above (4/8)
37220 | | from above (5/8)
37320 | | from above (6/8)
37420 | | from above (7/8)
37520 | | from above (8/8)
37661 | a | c7='abcd', the address of this is f7f7f7f7 (1/4)
37762 | b | from above (2/4)
37863 | c | from above (3/4)
37964 | d | from above (4/4)
380*/
381// clang-format on
382
383#ifndef TEMPTABLE_ROW_H
384#define TEMPTABLE_ROW_H
385
386#include <assert.h>
387#include <algorithm>
388
389#include "sql/field.h"
394
395namespace temptable {
396
397/** A row representation. A row consists of multiple cells.
398A row is created from a handler row (in write_row() format) and initially it
399refers the data in the provided handler row - without copying any user data.
400Nevertheless such a lightweight row can be used in the same way as a row
401that has copied the user data and owns it. */
402class Row {
403 public:
404 explicit Row(const unsigned char *mysql_row, Allocator<uint8_t> *allocator);
405
406 /** Copy constructing is disabled because it is too expensive. */
407 Row(const Row &) = delete;
408
409 /** Copy assignment is disabled because it is too expensive. */
410 Row &operator=(const Row &) = delete;
411
412 /** Move constructor. `other` is undefined after this call. */
413 Row(Row &&other) = delete;
414
415 /** Move assignment. `rhs` is undefined after this call. */
416 Row &operator=(Row &&rhs) = delete;
417
418 /** Destructor. */
419 ~Row();
420
421 /** Get a given cell. The cell contains pointers inside the row, so its
422 * lifetime should not be longer than the row.
423 * @return a cell from the row. */
424 Cell cell(
425 /** [in] Column that corresponds to this cell. */
426 const Column &column,
427 /** [in] The index of the cell to fetch (must be < number_of_cells()). */
428 size_t i) const;
429
430 /** Copy the user data to an own buffer (convert from write_row() format).
431 * @return Result:OK or other Result::* error code */
433 /** [in] Metadata for the columns that constitute this row. */
434 const Columns &columns,
435 /** [in] Length of the mysql row in bytes (m_ptr). */
436 size_t mysql_row_length) const;
437
438 /** Copy the row in a MySQL buffer (convert to write_row() format). */
440 /** [in] Metadata for the columns that constitute this row. */
441 const Columns &columns,
442 /** [out] Destination buffer to copy the row to. */
443 unsigned char *mysql_row,
444 /** [in] Presumed length of the mysql row in bytes. */
445 size_t mysql_row_length) const;
446
447 /** Swaps contents of two rows. */
448 static void swap(
449 /** [in,out] First row to swap. */
450 Row &r1,
451 /** [in,out] Seconds row to swap. */
452 Row &r2);
453
454#ifndef NDEBUG
455 /** Compare to another row. Used by Table::update() and Table::remove() to
456 * double check that the row which is passed as "old row" indeed equals to
457 * the row pointed to by the specified position.
458 * @retval <0 if lhs < rhs
459 * @retval 0 if lhs == rhs
460 * @retval >0 if lhs > rhs */
461 static int compare(
462 /** [in] First row to compare. */
463 const Row &lhs,
464 /** [in] Second row to compare. */
465 const Row &rhs,
466 /** [in] Columns that constitute `this` and in `rhs`. */
467 const Columns &columns,
468 /** [in] List of MySQL column definitions,
469 * used for querying metadata. */
470 Field **mysql_fields);
471#endif /* NDEBUG */
472
473 private:
474 /** Get a pointer to the cells array. Only defined if
475 * `m_data_is_in_mysql_memory` is false.
476 * @return cells array */
477 Cell *cells() const;
478
479 /** Get a given cell. The cell contains pointers inside the row, so its
480 * lifetime should not be longer than the row.
481 * @return a cell from the row. */
483 /** [in] The index of the cell to fetch (must be < number_of_cells()). */
484 size_t i) const;
485
486 /** Get a given cell. The cell contains pointers inside the row, so the
487 * returned cell's lifetime should not be longer than the row.
488 * @return a cell from the row. */
490 /** [in] Column that corresponds to this cell. */
491 const Column &column) const;
492
493 /** Derives the length of the buffer pointed to by `m_ptr` in bytes (when
494 * `m_data_is_in_mysql_memory` is false).
495 * @return buffer length */
496 size_t buf_length() const;
497
498 /** Allocator to use when copying from MySQL row to our own memory. */
500
501 /** Indicate whether this object is lightweight, with just pointers to the
502 * MySQL row buffer or not. */
504
505 /** A pointer to either the mysql row, or our buffer. If
506 * - `m_data_is_in_mysql_memory` is true, then this points to a buffer in
507 * mysql write_row() format, not owned by the current Row object;
508 * - `m_data_is_in_mysql_memory` is false, then this points a our own buffer
509 * that holds the cells and the user data. Its structure is:
510 * [0, A = sizeof(size_t)): buffer length
511 * [A, B = A + number_of_cells * sizeof(Cell)): cells array
512 * [B, B + sum(user data length for each cell)): user data of the cells */
513 mutable unsigned char *m_ptr;
514};
515
516/* Implementation of inlined methods. */
517
518inline void Row::swap(Row &r1, Row &r2) {
521 std::swap(r1.m_ptr, r2.m_ptr);
522}
523
524inline Row::Row(const unsigned char *mysql_row, Allocator<uint8_t> *allocator)
525 : m_allocator(allocator),
526 m_data_is_in_mysql_memory(true),
527 m_ptr(const_cast<unsigned char *>(mysql_row)) {}
528
529inline Row::~Row() {
530 if (!m_data_is_in_mysql_memory && m_ptr != nullptr) {
531 m_allocator->deallocate(m_ptr, buf_length());
532 }
533}
534
535inline Cell Row::cell(const Column &column, size_t i) const {
537 return cell_in_mysql_memory(column);
538 } else {
539 return cell_in_row(i);
540 }
541}
542
543inline Cell *Row::cells() const {
545 assert(m_ptr != nullptr);
546 return reinterpret_cast<Cell *>(m_ptr + sizeof(size_t));
547}
548
549inline Cell Row::cell_in_row(size_t i) const { return cells()[i]; }
550
551inline Cell Row::cell_in_mysql_memory(const Column &column) const {
553
554 const bool is_null = column.read_is_null(m_ptr);
555 const uint32_t data_length = column.read_user_data_length(m_ptr);
556 const unsigned char *data_ptr = column.get_user_data_ptr(m_ptr);
557
558 return Cell{is_null, data_length, data_ptr};
559}
560
561inline size_t Row::buf_length() const {
563 assert(m_ptr != nullptr);
564 return *reinterpret_cast<size_t *>(m_ptr);
565}
566
567} /* namespace temptable */
568
569#endif /* TEMPTABLE_ROW_H */
TempTable Cell declaration.
Definition: field.h:577
Custom memory allocator.
Definition: allocator.h:445
A cell is the intersection of a row and a column.
Definition: cell.h:42
A column class that describes the metadata of a column.
Definition: column.h:41
bool read_is_null(const unsigned char *mysql_row) const
Check if a particular cell is NULL.
Definition: column.h:235
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
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
A row representation.
Definition: row.h:402
Row(const unsigned char *mysql_row, Allocator< uint8_t > *allocator)
Definition: row.h:524
Row & operator=(Row &&rhs)=delete
Move assignment.
Cell * cells() const
Get a pointer to the cells array.
Definition: row.h:543
static void swap(Row &r1, Row &r2)
Swaps contents of two rows.
Definition: row.h:518
Allocator< uint8_t > * m_allocator
Allocator to use when copying from MySQL row to our own memory.
Definition: row.h:499
unsigned char * m_ptr
A pointer to either the mysql row, or our buffer.
Definition: row.h:513
Cell cell_in_row(size_t i) const
Get a given cell.
Definition: row.h:549
Cell cell(const Column &column, size_t i) const
Get a given cell.
Definition: row.h:535
Result copy_to_own_memory(const Columns &columns, size_t mysql_row_length) const
Copy the user data to an own buffer (convert from write_row() format).
Definition: row.cc:64
Row & operator=(const Row &)=delete
Copy assignment is disabled because it is too expensive.
void copy_to_mysql_row(const Columns &columns, unsigned char *mysql_row, size_t mysql_row_length) const
Copy the row in a MySQL buffer (convert to write_row() format).
Definition: row.cc:114
size_t buf_length() const
Derives the length of the buffer pointed to by m_ptr in bytes (when m_data_is_in_mysql_memory is fals...
Definition: row.h:561
~Row()
Destructor.
Definition: row.h:529
Cell cell_in_mysql_memory(const Column &column) const
Get a given cell.
Definition: row.h:551
bool m_data_is_in_mysql_memory
Indicate whether this object is lightweight, with just pointers to the MySQL row buffer or not.
Definition: row.h:503
Row(const Row &)=delete
Copy constructing is disabled because it is too expensive.
static int compare(const Row &lhs, const Row &rhs, const Columns &columns, Field **mysql_fields)
Compare to another row.
Definition: row.cc:46
Row(Row &&other)=delete
Move constructor.
Definition: allocator.h:48
Result
Definition: result.h:34
std::vector< Column, Allocator< Column > > Columns
A type that designates all the columns of a table.
Definition: column.h:227
static void swap(String &a, String &b) noexcept
Definition: sql_string.h:663
TempTable custom allocator.
TempTable Column declaration.
TempTable auxiliary Result enum.