MySQL 8.3.0
Source Code Documentation
row.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/row.h
24TempTable Row declarations. */
25
26// clang-format off
27/** @page PAGE_TEMPTABLE_ROW_FORMAT Row format
28
29The handler interface uses two different formats. Assume the following table:
30
31~~~~~~~~~~~~~{.sql}
32CREATE TABLE tt (
33 c1 INT(11) DEFAULT NULL,
34 c2 INT(11) NOT NULL,
35 c3 VARCHAR(8) DEFAULT NULL,
36 c4 VARCHAR(8) NOT NULL,
37 c5 CHAR(8) DEFAULT NULL,
38 c6 CHAR(8) NOT NULL,
39 c7 VARCHAR(300) DEFAULT NULL,
40 KEY `i1` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`)
41);
42~~~~~~~~~~~~~
43
44@section WRITE_ROW_FORMAT write_row() format
45
46This format is used in the input of the `write_row()` method. The same format
47is used by the storage engine in the output buffers of `rnd_next()` and
48`index_read()`. Consider the following INSERT statement:
49
50~~~~~~~~~~~~~{.sql}
51INSERT INTO t VALUES (123, 123, 'abcd', 'abcd', 'abcd', 'abcd', 'abcd');
52~~~~~~~~~~~~~
53
54the row buffer that is passed to `write_row()` is 352 bytes:
55
56hex | raw | description
57--- | --- | -----------
58f0 | . | NULLs bitmask 11110000 denoting that out of 4 columns that could possibly be NULL (c1, c3, c5 and c7) none is actually NULL.
597b | { | c1=123 stored in 4 bytes (little endian) (1/4)
6000 | . | from above (2/4)
6100 | . | from above (3/4)
6200 | . | from above (4/4)
637b | { | c2=123 stored in 4 bytes (little endian) (1/4)
6400 | . | from above (2/4)
6500 | . | from above (3/4)
6600 | . | from above (4/4)
6704 | . | the length of the following data (for VARCHAR cells): 4
6861 | a | c3='abcd' - the actual data (1/4)
6962 | b | from above (2/4)
7063 | c | from above (3/4)
7164 | d | from above (4/4)
72a5 | . | 4 wasted bytes for c3 (1/4)
73a5 | . | from above (2/4)
74a5 | . | from above (3/4)
75a5 | . | from above (4/4)
7604 | . | the length of the following data (for VARCHAR cells): 4
7761 | a | c4='abcd' - the actual data (1/4)
7862 | b | from above (2/4)
7963 | c | from above (3/4)
8064 | d | from above (4/4)
81a5 | . | 4 wasted bytes for c4 (1/4)
82a5 | . | from above (2/4)
83a5 | . | from above (3/4)
84a5 | . | from above (4/4)
8561 | a | c5='abcd ' (padded to 8 bytes with spaces at the end) (1/8)
8662 | b | from above (2/8)
8763 | c | from above (3/8)
8864 | d | from above (4/8)
8920 | | from above (5/8)
9020 | | from above (6/8)
9120 | | from above (7/8)
9220 | | from above (8/8)
9361 | a | c6='abcd ' (padded to 8 bytes with spaces at the end) (1/8)
9462 | b | from above (2/8)
9563 | c | from above (3/8)
9664 | d | from above (4/8)
9720 | | from above (5/8)
9820 | | from above (6/8)
9920 | | from above (7/8)
10020 | | from above (8/8)
10104 | . | the length (occupying 2 bytes) of the following data (for VARCHAR cells): 4 (1/2)
10200 | . | from above (2/2)
10361 | a | c7='abcd' - the actual data (1/4)
10462 | b | from above (2/4)
10563 | c | from above (3/4)
10664 | d | from above (4/4)
107a5 | . | a5 repeats 296 times, wasted bytes for c7 (1/296)
108a5 | . | from above (2/296)
109.. | .. | ..
110a5 | . | from above (296/296)
111
112@section INDEX_READ_FORMAT index_read() format
113
114Consider the following SELECT statement:
115
116~~~~~~~~~~~~~{.sql}
117SELECT * FROM t WHERE
118c1=123 AND
119c2=123 AND
120c3='abcd' AND
121c4='abcd' AND
122c5='abcd' AND
123c6='abcd' AND
124c7='abcd';
125~~~~~~~~~~~~~
126
127the indexed cells buffer that is passed to `index_read()` is 350 bytes:
128
129hex | raw | description
130--- | --- | -----------
13100 | . | c1 NULL byte, denoting that c1 is not NULL (would have been 01 is c1 was NULL)
1327b | { | c1=123 stored in 4 bytes (little endian) (1/4)
13300 | . | from above (2/4)
13400 | . | from above (3/4)
13500 | . | from above (4/4)
1367b | { | 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)
13700 | . | from above (2/4)
13800 | . | from above (3/4)
13900 | . | from above (4/4)
14000 | . | c3 NULL byte, denoting that c3 is not NULL (would have been 01 if c3 was NULL)
14104 | . | c3 length (4), always 2 bytes (1/2)
14200 | . | from above (2/2)
14361 | a | c3='abcd' - the actual data (1/4)
14462 | b | from above (2/4)
14563 | c | from above (3/4)
14664 | d | from above (4/4)
14700 | . | 4 wasted bytes for c3 (1/4)
14800 | . | from above (2/4)
14900 | . | from above (3/4)
15000 | . | from above (4/4)
15104 | . | c4 length (4), always 2 bytes (no NULL byte for c4) (1/2)
15200 | . | from above (2/2)
15361 | a | c4='abcd' - the actual data (1/4)
15462 | b | from above (2/4)
15563 | c | from above (3/4)
15664 | d | from above (4/4)
15700 | . | 4 wasted bytes for c4 (1/4)
15800 | . | from above (2/4)
15900 | . | from above (3/4)
16000 | . | from above (4/4)
16100 | . | c5 NULL byte, denoting that c5 is not NULL (would have been 01 if c5 was NULL)
16261 | a | c5='abcd ' (1/8)
16362 | b | from above (2/8)
16463 | c | from above (3/8)
16564 | d | from above (4/8)
16620 | | from above (5/8)
16720 | | from above (6/8)
16820 | | from above (7/8)
16920 | | from above (8/8)
17061 | a | c6='abcd ' (c6 cannot be NULL) (1/8)
17162 | b | from above (2/8)
17263 | c | from above (3/8)
17364 | d | from above (4/8)
17420 | | from above (5/8)
17520 | | from above (6/8)
17620 | | from above (7/8)
17720 | | from above (8/8)
17800 | . | c7 NULL byte
17904 | . | c7 length (4), always 2 bytes (1/2)
18000 | . | from above (2/2)
18161 | a | c7='abcd' - the actual data (1/4)
18262 | b | from above (2/4)
18363 | c | from above (3/4)
18464 | d | from above (4/4)
18500 | . | 296 wasted bytes for c7 (1/296)
18600 | . | from above (2/296)
187.. | .. | ..
18800 | . | from above (296/296)
189
190@section TEMPTABLE_FORMAT TempTable format
191
192We introduce a new format, lets call it TempTable format, that fulfills the
193following:
194
1951. Does not waste space for VARCHAR cells
1962. It must be possible to convert from write_row() format to this new format
1973. It must be possible to convert the new format to write_row() format
1984. When a row is stored internally in this new format, it must be possible
199 to compare its relevant cells to cells in the index_read() format without
200 any heap memory allocation (malloc()/new) and without copying of user
201 data (memcpy()).
202
203For this we introduce a Cell class, which has the following properties:
2041. NULL byte (bool, 1 byte)
2052. user data length (uint32_t, 4 bytes)
2063. pointer to the user data (void*, 8 bytes on 64-bit machines)
2074. can compare itself to another cell
2085. can hash itself
209
210A Cell object does not store actual user data, only a pointer to it. This way
211we can create cells that point inside the buffer provided to `write_row()` or
212point inside our own buffer, where the user data is copied for storage.
213
214A row in the TempTable format consists of a set of Cells stored in one buffer,
215together with the actual user data. The size of a row is the size of all
216user data + 16 bytes overhead for each cell (for the Cell object).
217
218In the above example both the row (`write_row()` format) and the indexed cells
219(`index_read()` format) would be represented like in the table below, in 148
220bytes. Think of a POD
221~~~~~~~~~~~~~{.cpp}
222struct Cell {
223 bool is_null;
224 uint32_t len;
225 void* data;
226};
227~~~~~~~~~~~~~
228
229hex | raw | description
230--- | --- | -----------
23100 | . | c1 NULL byte (00 means not NULL)
23200 | . | 3 bytes padding (1/3)
23300 | . | from above (2/3)
23400 | . | from above (3/3)
23500 | . | c1 length in 4 bytes in whatever is the machine's native byte order (1/4)
23600 | . | from above (2/4)
23700 | . | from above (3/4)
23804 | . | from above (4/4)
239f1 | . | address in memory where c1 user data is stored (1/8)
240f1 | . | from above (2/8)
241f1 | . | from above (3/8)
242f1 | . | from above (4/8)
243f1 | . | from above (5/8)
244f1 | . | from above (6/8)
245f1 | . | from above (7/8)
246f1 | . | from above (8/8)
24700 | . | c2 NULL byte (00 means not NULL)
24800 | . | 3 bytes padding (1/3)
24900 | . | from above (2/3)
25000 | . | from above (3/3)
25100 | . | c2 length in 4 bytes in whatever is the machine's native byte order (1/4)
25200 | . | from above (2/4)
25300 | . | from above (3/4)
25404 | . | from above (4/4)
255f2 | . | address in memory where c2 user data is stored (1/8)
256f2 | . | from above (2/8)
257f2 | . | from above (3/8)
258f2 | . | from above (4/8)
259f2 | . | from above (5/8)
260f2 | . | from above (6/8)
261f2 | . | from above (7/8)
262f2 | . | from above (8/8)
26300 | . | c3 NULL byte (00 means not NULL)
26400 | . | 3 bytes padding (1/3)
26500 | . | from above (2/3)
26600 | . | from above (3/3)
26700 | . | c3 length in 4 bytes in whatever is the machine's native byte order (1/4)
26800 | . | from above (2/4)
26900 | . | from above (3/4)
27004 | . | from above (4/4)
271f3 | . | address in memory where c3 user data is stored (1/8)
272f3 | . | from above (2/8)
273f3 | . | from above (3/8)
274f3 | . | from above (4/8)
275f3 | . | from above (5/8)
276f3 | . | from above (6/8)
277f3 | . | from above (7/8)
278f3 | . | from above (8/8)
27900 | . | c4 NULL byte (00 means not NULL)
28000 | . | 3 bytes padding (1/3)
28100 | . | from above (2/3)
28200 | . | from above (3/3)
28300 | . | c4 length in 4 bytes in whatever is the machine's native byte order (1/4)
28400 | . | from above (2/4)
28500 | . | from above (3/4)
28604 | . | from above (4/4)
287f4 | . | address in memory where c4 user data is stored (1/8)
288f4 | . | from above (2/8)
289f4 | . | from above (3/8)
290f4 | . | from above (4/8)
291f4 | . | from above (5/8)
292f4 | . | from above (6/8)
293f4 | . | from above (7/8)
294f4 | . | from above (8/8)
29500 | . | c5 NULL byte (00 means not NULL)
29600 | . | 3 bytes padding (1/3)
29700 | . | from above (2/3)
29800 | . | from above (3/3)
29900 | . | c5 length in 4 bytes in whatever is the machine's native byte order (1/4)
30000 | . | from above (2/4)
30100 | . | from above (3/4)
30208 | . | from above (4/4)
303f5 | . | address in memory where c5 user data is stored (1/8)
304f5 | . | from above (2/8)
305f5 | . | from above (3/8)
306f5 | . | from above (4/8)
307f5 | . | from above (5/8)
308f5 | . | from above (6/8)
309f5 | . | from above (7/8)
310f5 | . | from above (8/8)
31100 | . | c6 NULL byte (00 means not NULL)
31200 | . | 3 bytes padding (1/3)
31300 | . | from above (2/3)
31400 | . | from above (3/3)
31500 | . | c6 length in 4 bytes in whatever is the machine's native byte order (1/4)
31600 | . | from above (2/4)
31700 | . | from above (3/4)
31808 | . | from above (4/4)
319f6 | . | address in memory where c6 user data is stored (1/8)
320f6 | . | from above (2/8)
321f6 | . | from above (3/8)
322f6 | . | from above (4/8)
323f6 | . | from above (5/8)
324f6 | . | from above (6/8)
325f6 | . | from above (7/8)
326f6 | . | from above (8/8)
32700 | . | c7 NULL byte (00 means not NULL)
32800 | . | 3 bytes padding (1/3)
32900 | . | from above (2/3)
33000 | . | from above (3/3)
33100 | . | c7 length in 4 bytes in whatever is the machine's native byte order (1/4)
33200 | . | from above (2/4)
33300 | . | from above (3/4)
33404 | . | from above (4/4)
335f7 | . | address in memory where c7 user data is stored (1/8)
336f7 | . | from above (2/8)
337f7 | . | from above (3/8)
338f7 | . | from above (4/8)
339f7 | . | from above (5/8)
340f7 | . | from above (6/8)
341f7 | . | from above (7/8)
342f7 | . | from above (8/8)
3437b | { | c1=123, the address of this is f1f1f1f1 (1/4)
34400 | . | from above (2/4)
34500 | . | from above (3/4)
34600 | . | from above (4/4)
3477b | { | c2=123, the address of this is f2f2f2f2 (1/4)
34800 | . | from above (2/4)
34900 | . | from above (3/4)
35000 | . | from above (4/4)
35161 | a | c3='abcd', the address of this is f3f3f3f3 (1/4)
35262 | b | from above (2/4)
35363 | c | from above (3/4)
35464 | d | from above (4/4)
35561 | a | c4='abcd', the address of this is f4f4f4f4 (1/4)
35662 | b | from above (2/4)
35763 | c | from above (3/4)
35864 | d | from above (4/4)
35961 | a | c5='abcd ', the address of this is f5f5f5f5 (1/8)
36062 | b | from above (2/8)
36163 | c | from above (3/8)
36264 | d | from above (4/8)
36320 | | from above (5/8)
36420 | | from above (6/8)
36520 | | from above (7/8)
36620 | | from above (8/8)
36761 | a | c6='abcd ', the address of this is f6f6f6f6 (1/8)
36862 | b | from above (2/8)
36963 | c | from above (3/8)
37064 | d | from above (4/8)
37120 | | from above (5/8)
37220 | | from above (6/8)
37320 | | from above (7/8)
37420 | | from above (8/8)
37561 | a | c7='abcd', the address of this is f7f7f7f7 (1/4)
37662 | b | from above (2/4)
37763 | c | from above (3/4)
37864 | d | from above (4/4)
379*/
380// clang-format on
381
382#ifndef TEMPTABLE_ROW_H
383#define TEMPTABLE_ROW_H
384
385#include <assert.h>
386#include <algorithm>
387
388#include "sql/field.h"
393
394namespace temptable {
395
396/** A row representation. A row consists of multiple cells.
397A row is created from a handler row (in write_row() format) and initially it
398refers the data in the provided handler row - without copying any user data.
399Nevertheless such a lightweight row can be used in the same way as a row
400that has copied the user data and owns it. */
401class Row {
402 public:
403 explicit Row(const unsigned char *mysql_row, Allocator<uint8_t> *allocator);
404
405 /** Copy constructing is disabled because it is too expensive. */
406 Row(const Row &) = delete;
407
408 /** Copy assignment is disabled because it is too expensive. */
409 Row &operator=(const Row &) = delete;
410
411 /** Move constructor. `other` is undefined after this call. */
412 Row(Row &&other) = delete;
413
414 /** Move assignment. `rhs` is undefined after this call. */
415 Row &operator=(Row &&rhs) = delete;
416
417 /** Destructor. */
418 ~Row();
419
420 /** Get a given cell. The cell contains pointers inside the row, so its
421 * lifetime should not be longer than the row.
422 * @return a cell from the row. */
423 Cell cell(
424 /** [in] Column that corresponds to this cell. */
425 const Column &column,
426 /** [in] The index of the cell to fetch (must be < number_of_cells()). */
427 size_t i) const;
428
429 /** Copy the user data to an own buffer (convert from write_row() format).
430 * @return Result:OK or other Result::* error code */
432 /** [in] Metadata for the columns that constitute this row. */
433 const Columns &columns,
434 /** [in] Length of the mysql row in bytes (m_ptr). */
435 size_t mysql_row_length) const;
436
437 /** Copy the row in a MySQL buffer (convert to write_row() format). */
439 /** [in] Metadata for the columns that constitute this row. */
440 const Columns &columns,
441 /** [out] Destination buffer to copy the row to. */
442 unsigned char *mysql_row,
443 /** [in] Presumed length of the mysql row in bytes. */
444 size_t mysql_row_length) const;
445
446 /** Swaps contents of two rows. */
447 static void swap(
448 /** [in,out] First row to swap. */
449 Row &r1,
450 /** [in,out] Seconds row to swap. */
451 Row &r2);
452
453#ifndef NDEBUG
454 /** Compare to another row. Used by Table::update() and Table::remove() to
455 * double check that the row which is passed as "old row" indeed equals to
456 * the row pointed to by the specified position.
457 * @retval <0 if lhs < rhs
458 * @retval 0 if lhs == rhs
459 * @retval >0 if lhs > rhs */
460 static int compare(
461 /** [in] First row to compare. */
462 const Row &lhs,
463 /** [in] Second row to compare. */
464 const Row &rhs,
465 /** [in] Columns that constitute `this` and in `rhs`. */
466 const Columns &columns,
467 /** [in] List of MySQL column definitions,
468 * used for querying metadata. */
469 Field **mysql_fields);
470#endif /* NDEBUG */
471
472 private:
473 /** Get a pointer to the cells array. Only defined if
474 * `m_data_is_in_mysql_memory` is false.
475 * @return cells array */
476 Cell *cells() const;
477
478 /** Get a given cell. The cell contains pointers inside the row, so its
479 * lifetime should not be longer than the row.
480 * @return a cell from the row. */
482 /** [in] The index of the cell to fetch (must be < number_of_cells()). */
483 size_t i) const;
484
485 /** Get a given cell. The cell contains pointers inside the row, so the
486 * returned cell's lifetime should not be longer than the row.
487 * @return a cell from the row. */
489 /** [in] Column that corresponds to this cell. */
490 const Column &column) const;
491
492 /** Derives the length of the buffer pointed to by `m_ptr` in bytes (when
493 * `m_data_is_in_mysql_memory` is false).
494 * @return buffer length */
495 size_t buf_length() const;
496
497 /** Allocator to use when copying from MySQL row to our own memory. */
499
500 /** Indicate whether this object is lightweight, with just pointers to the
501 * MySQL row buffer or not. */
503
504 /** A pointer to either the mysql row, or our buffer. If
505 * - `m_data_is_in_mysql_memory` is true, then this points to a buffer in
506 * mysql write_row() format, not owned by the current Row object;
507 * - `m_data_is_in_mysql_memory` is false, then this points a our own buffer
508 * that holds the cells and the user data. Its structure is:
509 * [0, A = sizeof(size_t)): buffer length
510 * [A, B = A + number_of_cells * sizeof(Cell)): cells array
511 * [B, B + sum(user data length for each cell)): user data of the cells */
512 mutable unsigned char *m_ptr;
513};
514
515/* Implementation of inlined methods. */
516
517inline void Row::swap(Row &r1, Row &r2) {
520 std::swap(r1.m_ptr, r2.m_ptr);
521}
522
523inline Row::Row(const unsigned char *mysql_row, Allocator<uint8_t> *allocator)
524 : m_allocator(allocator),
525 m_data_is_in_mysql_memory(true),
526 m_ptr(const_cast<unsigned char *>(mysql_row)) {}
527
528inline Row::~Row() {
529 if (!m_data_is_in_mysql_memory && m_ptr != nullptr) {
530 m_allocator->deallocate(m_ptr, buf_length());
531 }
532}
533
534inline Cell Row::cell(const Column &column, size_t i) const {
536 return cell_in_mysql_memory(column);
537 } else {
538 return cell_in_row(i);
539 }
540}
541
542inline Cell *Row::cells() const {
544 assert(m_ptr != nullptr);
545 return reinterpret_cast<Cell *>(m_ptr + sizeof(size_t));
546}
547
548inline Cell Row::cell_in_row(size_t i) const { return cells()[i]; }
549
550inline Cell Row::cell_in_mysql_memory(const Column &column) const {
552
553 const bool is_null = column.read_is_null(m_ptr);
554 const uint32_t data_length = column.read_user_data_length(m_ptr);
555 const unsigned char *data_ptr = column.get_user_data_ptr(m_ptr);
556
557 return Cell{is_null, data_length, data_ptr};
558}
559
560inline size_t Row::buf_length() const {
562 assert(m_ptr != nullptr);
563 return *reinterpret_cast<size_t *>(m_ptr);
564}
565
566} /* namespace temptable */
567
568#endif /* TEMPTABLE_ROW_H */
TempTable Cell declaration.
Definition: field.h:574
Custom memory allocator.
Definition: allocator.h:353
A cell is the intersection of a row and a column.
Definition: cell.h:41
A column class that describes the metadata of a column.
Definition: column.h:40
bool read_is_null(const unsigned char *mysql_row) const
Check if a particular cell is NULL.
Definition: column.h:234
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
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
A row representation.
Definition: row.h:401
Row & operator=(Row &&rhs)=delete
Move assignment.
Cell cell_in_row(size_t i) const
Get a given cell.
Definition: row.h:548
Allocator< uint8_t > * m_allocator
Allocator to use when copying from MySQL row to our own memory.
Definition: row.h:498
Cell cell(const Column &column, size_t i) const
Get a given cell.
Definition: row.h:534
Cell cell_in_mysql_memory(const Column &column) const
Get a given cell.
Definition: row.h:550
unsigned char * m_ptr
A pointer to either the mysql row, or our buffer.
Definition: row.h:512
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:63
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:560
static void swap(Row &r1, Row &r2)
Swaps contents of two rows.
Definition: row.h:517
static int compare(const Row &lhs, const Row &rhs, const Columns &columns, Field **mysql_fields)
Compare to another row.
Definition: row.cc:45
~Row()
Destructor.
Definition: row.h:528
Row & operator=(const Row &)=delete
Copy assignment is disabled because it is too expensive.
Cell * cells() const
Get a pointer to the cells array.
Definition: row.h:542
Row(const unsigned char *mysql_row, Allocator< uint8_t > *allocator)
Definition: row.h:523
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:502
Row(const Row &)=delete
Copy constructing 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:113
Row(Row &&other)=delete
Move constructor.
Definition: allocator.h:44
Result
Definition: result.h:33
std::vector< Column, Allocator< Column > > Columns
A type that designates all the columns of a table.
Definition: column.h:226
TempTable custom allocator.
TempTable Column declaration.
TempTable auxiliary Result enum.
void swap(const varlen_element &a, const varlen_element &b)
Definition: varlen_sort.h:65