MySQL 9.2.0
Source Code Documentation
pack_rows.h
Go to the documentation of this file.
1#ifndef SQL_PACK_ROWS_H_
2#define SQL_PACK_ROWS_H_
3
4/* Copyright (c) 2020, 2024, Oracle and/or its affiliates.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2.0,
8 as published by the Free Software Foundation.
9
10 This program is designed to work with certain software (including
11 but not limited to OpenSSL) that is licensed under separate terms,
12 as designated in a particular file or component or in included license
13 documentation. The authors of MySQL hereby grant you an additional
14 permission to link the program and your derivative works with the
15 separately licensed software that they have either included with
16 the program or referenced in the documentation.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License, version 2.0, for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
26
27/**
28 @file
29
30 Generic routines for packing rows (possibly from multiple tables
31 at the same time) into strings, and then back again. Used for (at least)
32 hash join, BKA, and streaming aggregation.
33 */
34
35#include <cassert>
36#include <cstddef>
37#include <cstring>
38
39#include "field_types.h"
40#include "my_bitmap.h"
41#include "my_compiler.h"
42
43#include "my_inttypes.h"
44#include "my_table_map.h"
46#include "prealloced_array.h"
47#include "sql/field.h"
48#include "sql/handler.h"
49#include "sql/table.h"
50
51class String;
52
53// Names such as “Column” and “Table” are a tad too generic for the global
54// namespace.
55namespace pack_rows {
56
57/// A class that represents a field, which also holds a cached value of the
58/// field's data type.
59struct Column {
60 explicit Column(Field *field);
61 Field *const field;
62
63 // The field type is used frequently, and caching it gains around 30% in some
64 // of our microbenchmarks.
66};
67
68/// This struct is primarily used for holding the extracted columns in a hash
69/// join or BKA join, or the input columns in a streaming aggregation operation.
70/// When the join or aggregate iterator is constructed, we extract the columns
71/// that are needed to satisfy the SQL query.
72struct Table {
73 explicit Table(TABLE *table_arg);
76
77 // Whether to copy the NULL flags or not.
78 bool copy_null_flags{false};
79};
80
81/// A structure that contains a list of input tables for a hash join operation,
82/// BKA join operation or a streaming aggregation operation, and some
83/// pre-computed properties for the tables.
85 public:
86 TableCollection() = default;
87
90
91 const Prealloced_array<Table, 4> &tables() const { return m_tables; }
92
94
96
97 bool has_blob_column() const { return m_has_blob_column; }
98
99 bool store_rowids() const { return m_store_rowids; }
100
103 }
104
105 /// For each of the tables that we should get row IDs for, request that the
106 /// row ID is filled in (the equivalent of calling handler::position()) if
107 /// needed.
108 ///
109 /// Since this function is typically called once per row read, the check for
110 /// the common case where no row IDs are required, is inlined to reduce the
111 /// overhead.
112 void RequestRowId() const {
113 if (m_tables_to_get_rowid_for != 0) {
115 }
116 }
117
118 /// For each of the tables that we should get row IDs for, inform the handler
119 /// than row IDs will be needed.
120 void PrepareForRequestRowId() const;
121
122 private:
123 void AddTable(TABLE *tab);
124 void RequestRowIdInner() const;
125
127
128 // We frequently use the bitmap to determine which side of the join an Item
129 // belongs to, so precomputing the bitmap saves quite some time.
131
132 // Sum of the NULL bytes and the row ID for all of the tables.
134
135 // Whether any of the tables has a BLOB/TEXT column. This is used to determine
136 // whether we need to estimate the row size every time we store a row to the
137 // row buffer or to a chunk file on disk. If this is set to false, we can
138 // pre-allocate any necessary buffers we need during the operation, and thus
139 // eliminate the need for recalculating the row size every time.
140 bool m_has_blob_column = false;
141
142 bool m_store_rowids = false;
144};
145
146/// Count up how many bytes a single row from the given tables will occupy,
147/// in "packed" format. Note that this is an upper bound, so the length after
148/// calling Field::pack may very well be shorter than the size returned by this
149/// function.
150///
151/// The value returned from this function will sum up
152/// 1) The row-id if that is to be kept.
153/// 2) Size of the NULL flags. This includes:
154/// - Space for a NULL flag per nullable column.
155/// - Space for a NULL flag per nullable table (tables on the inner side of
156/// an outer join).
157/// 3) Size of the buffer returned by pack() on all columns marked in the
158/// \c read_set_internal.
159/// We do not necessarily have valid data in the table buffers, so we do not try
160/// to calculate size for blobs.
162/// Similar to ComputeRowSizeUpperBoundSansBlobs, but will calculate blob size
163/// as well. To do this, we need to look at the data stored in the record
164/// buffers.
165/// \note{This means that the function cannot be called without making sure
166/// there is valid data in the table buffers.}
167size_t ComputeRowSizeUpperBound(const TableCollection &tables);
168
169/// Take the data marked for reading in "tables" and store it in the provided
170/// buffer. What data to store is determined by the read set of each table.
171/// Note that any existing data in "buffer" will be overwritten.
172///
173/// The output buffer will contain the following data for each table in
174/// "tables":
175///
176/// 1) NULL-row flag if the table is nullable.
177/// 2) NULL flags for each nullable column.
178/// 3) The actual data from the columns.
179/// 4) The row ID for each row. This is only stored if the optimizer requested
180/// row IDs when creating the TableCollection.
181///
182/// @retval true if error, false otherwise
184
185/// Take the data in "ptr" and put it back to the tables' record buffers.
186/// The tables must be _exactly_ the same as when the row was created.
187/// That is, it must contain the same tables in the same order, and the read set
188/// of each table must be identical when storing and restoring the row.
189/// If that's not the case, you will end up with undefined and unpredictable
190/// behavior.
191///
192/// Returns a pointer to where we ended reading.
193const uchar *LoadIntoTableBuffers(const TableCollection &tables,
194 const uchar *ptr);
195
196inline bool ShouldCopyRowId(const TABLE *table) {
197 // It is not safe to copy the row ID if we have a NULL-complemented row; the
198 // value is undefined, or the buffer location can even be nullptr.
199 return !table->const_table && !(table->is_nullable() && table->null_row);
200}
201
203 uchar *dptr) {
204 for (const Table &tbl : tables.tables()) {
205 const TABLE *table = tbl.table;
206
207 bool null_row_flag = false;
208 if (table->is_nullable()) {
209 null_row_flag = table->has_null_row();
210 *dptr++ = uchar{null_row_flag};
211 }
212
213 // Store the NULL flags.
214 if (tbl.copy_null_flags) {
215 memcpy(dptr, table->null_flags, table->s->null_bytes);
216 dptr += table->s->null_bytes;
217 }
218
219 for (const Column &column : tbl.columns) {
221 column.field->field_index()));
222 if (!column.field->is_null()) {
223 // Store the data in packed format. The packed format will also
224 // include the length of the data if needed.
225 dptr = column.field->pack(dptr);
226 }
227 }
228
229 if (tables.store_rowids() && ShouldCopyRowId(table)) {
230 // Store the row ID, since it is needed by weedout.
231 memcpy(dptr, table->file->ref, table->file->ref_length);
232 dptr += table->file->ref_length;
233 }
234 }
235 return dptr;
236}
237
238} // namespace pack_rows
239
240#endif // SQL_PACK_ROWS_H_
Definition: field.h:577
TABLE * table
Pointer to TABLE object that owns this field.
Definition: field.h:683
uint16 field_index() const
Returns field index.
Definition: field.h:1840
bool is_null(ptrdiff_t row_offset=0) const
Check whether the full table's row is NULL or the Field has value NULL.
Definition: field.h:1229
virtual uchar * pack(uchar *to, const uchar *from, size_t max_length) const
Pack the field into a format suitable for storage and transfer.
Definition: field.cc:2033
A typesafe replacement for DYNAMIC_ARRAY.
Definition: prealloced_array.h:71
Using this class is fraught with peril, and you need to be very careful when doing so.
Definition: sql_string.h:167
A structure that contains a list of input tables for a hash join operation, BKA join operation or a s...
Definition: pack_rows.h:84
Prealloced_array< Table, 4 > m_tables
Definition: pack_rows.h:126
void RequestRowId() const
For each of the tables that we should get row IDs for, request that the row ID is filled in (the equi...
Definition: pack_rows.h:112
table_map tables_to_get_rowid_for() const
Definition: pack_rows.h:101
bool has_blob_column() const
Definition: pack_rows.h:97
bool store_rowids() const
Definition: pack_rows.h:99
void RequestRowIdInner() const
Definition: pack_rows.cc:289
bool m_store_rowids
Definition: pack_rows.h:142
void AddTable(TABLE *tab)
Definition: pack_rows.cc:73
size_t ref_and_null_bytes_size() const
Definition: pack_rows.h:95
table_map m_tables_bitmap
Definition: pack_rows.h:130
table_map m_tables_to_get_rowid_for
Definition: pack_rows.h:143
size_t m_ref_and_null_bytes_size
Definition: pack_rows.h:133
void PrepareForRequestRowId() const
For each of the tables that we should get row IDs for, inform the handler than row IDs will be needed...
Definition: pack_rows.cc:302
table_map tables_bitmap() const
Definition: pack_rows.h:93
const Prealloced_array< Table, 4 > & tables() const
Definition: pack_rows.h:91
bool m_has_blob_column
Definition: pack_rows.h:140
This file contains the field type.
enum_field_types
Column types for MySQL Note: Keep include/mysql/components/services/bits/stored_program_bits....
Definition: field_types.h:55
static bool bitmap_is_set(const MY_BITMAP *map, uint bit)
Definition: my_bitmap.h:95
Header for compiler-dependent features.
#define ALWAYS_INLINE
Definition: my_compiler.h:99
Some integer typedefs for easier portability.
unsigned char uchar
Definition: my_inttypes.h:52
uint64_t table_map
Definition: my_table_map.h:30
static PFS_engine_table_share_proxy table
Definition: pfs.cc:61
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:418
Definition: pack_rows.cc:35
bool ShouldCopyRowId(const TABLE *table)
Definition: pack_rows.h:196
bool StoreFromTableBuffers(const TableCollection &tables, String *buffer)
Take the data marked for reading in "tables" and store it in the provided buffer.
Definition: pack_rows.cc:230
ALWAYS_INLINE uchar * StoreFromTableBuffersRaw(const TableCollection &tables, uchar *dptr)
Definition: pack_rows.h:202
size_t ComputeRowSizeUpperBound(const TableCollection &tables)
Similar to ComputeRowSizeUpperBoundSansBlobs, but will calculate blob size as well.
Definition: pack_rows.cc:195
const uchar * LoadIntoTableBuffers(const TableCollection &tables, const uchar *ptr)
Take the data in "ptr" and put it back to the tables' record buffers.
Definition: pack_rows.cc:256
size_t ComputeRowSizeUpperBoundSansBlobs(const TableCollection &tables)
Count up how many bytes a single row from the given tables will occupy, in "packed" format.
Definition: pack_rows.cc:212
Performance schema instrumentation interface.
Definition: table.h:1421
MY_BITMAP read_set_internal
A bitmap of fields that are explicitly referenced by the query.
Definition: table.h:1739
A class that represents a field, which also holds a cached value of the field's data type.
Definition: pack_rows.h:59
const enum_field_types field_type
Definition: pack_rows.h:65
Field *const field
Definition: pack_rows.h:61
Column(Field *field)
Definition: pack_rows.cc:37
This struct is primarily used for holding the extracted columns in a hash join or BKA join,...
Definition: pack_rows.h:72
Table(TABLE *table_arg)
Definition: pack_rows.cc:42
bool copy_null_flags
Definition: pack_rows.h:78
Prealloced_array< Column, 8 > columns
Definition: pack_rows.h:75
TABLE * table
Definition: pack_rows.h:74
#define PSI_NOT_INSTRUMENTED
Definition: validate_password_imp.cc:44