MySQL 9.7.0
Source Code Documentation
row_proxy.h
Go to the documentation of this file.
1/* Copyright (c) 2024, 2026, Oracle and/or its affiliates.
2
3This program is free software; you can redistribute it and/or modify
4it under the terms of the GNU General Public License, version 2.0,
5as published by the Free 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,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License, version 2.0, for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef ROW_PROXY_H
25#define ROW_PROXY_H
26
27#include <array> // std::array
28#include <cstring> // std::strlen
31
35
36/// Framework that helps consuming data in a specific format, typically provided
37/// by a service API, and publishes that data in the form of a
38/// performance_schema table.
39///
40/// The format of a row is
41
42/// Data types that this framework supports storing in a table.
44 /// BIGINT, stored in the backend data as long long
46 /// ENUM, stored in the backend data as long long
48 /// TIMESTAMP, stored in the backend data as microseconds in long long
50 /// CHAR(...), stored as a char *.
52};
53
54/// Description of the mapping between a column and a field typecode.
55///
56/// @tparam Typecode_tp The enum type used for type codes.
57/// @tparam typecode_end_tp Enum value whose value is greater than the largest
58/// enum value that represents a field in a packet.
59template <class Typecode_tp, Typecode_tp typecode_end_tp>
60 requires requires { std::is_enum_v<Typecode_tp>; }
62 using Typecode_t = Typecode_tp;
63 static constexpr Typecode_t typecode_end = typecode_end_tp;
64 /// Enum value for the mysql::abi_helpers::Field object holding the value.
66 /// Type of the field.
68 /// Enum value for a mysql::abi_helpers::Field object that holds a bool
69 /// indicating if the value is NULL.
70 ///
71 /// @note: this is only a remainder of a legacy protocol: new protocols should
72 /// just omit m_field_typecode from the packet to indicate that the field is
73 /// NULL, and their Field_view_definitions should leave this field with the
74 /// default value.
75 Typecode_t m_null_typecode{typecode_end_tp};
76};
77
78/// Description of the mapping between columns and field typecodes, for all
79/// columns in a table.
80template <class Typecode_tp, Typecode_tp typecode_end_tp,
81 std::size_t column_count_tp>
83 std::array<Field_view_definition<Typecode_tp, typecode_end_tp>,
84 column_count_tp>;
85
86/// Forward declaration.
87template <class Typecode_tp, Typecode_tp typecode_end_tp,
88 std::size_t column_count_tp>
89 requires requires { std::is_enum_v<Typecode_tp>; }
90class Row_proxy;
91
92/// Aggregates type definitions and constants for a given typecode enum, end
93/// element of that enum, and column count.
94template <class Typecode_tp, Typecode_tp typecode_end_tp,
95 std::size_t column_count_tp>
97 using Typecode_t = Typecode_tp;
98 static constexpr Typecode_t typecode_end = typecode_end_tp;
99 static constexpr std::size_t column_count = column_count_tp;
100
106
110};
111
112extern REQUIRES_SERVICE_PLACEHOLDER(pfs_plugin_column_string_v2);
113extern REQUIRES_SERVICE_PLACEHOLDER(pfs_plugin_column_bigint_v1);
114extern REQUIRES_SERVICE_PLACEHOLDER(pfs_plugin_column_timestamp_v2);
115extern REQUIRES_SERVICE_PLACEHOLDER(pfs_plugin_column_enum_v1);
116
117/// Fills values in fields in a table row, using an
118/// Array_view<Field<Typecode_tp>> as data source (in namespace
119/// mysql::abi_helpers), for a given enum type Typecode_tp.
120///
121/// This does not copy or allocate data; internally it only holds fixed-size
122/// arrays that map column numbers to type codes in the enum type, and in turn
123/// each type code to a field in the row. Using this information, when queried
124/// with a column index and a PSI_field, it fills the PSI_field with the correct
125/// value from the source data.
126///
127/// The object is meant to be reused for multiple queries to the same table. At
128/// construction time, it creates the map associating column number with type
129/// code, and for each row the user gives, it recreates the map from type codes
130/// to field data.
131///
132/// @tparam Typecode_tp enum type that identifies each column, used in the
133/// template argument of Field.
134///
135/// @tparam typecode_end_tp enum item whose numeric value is greater than the
136/// largest enum value that represents a field in a packet.
137///
138/// @tparam column_count_tp The number of columns in the table.
139template <class Typecode_tp, Typecode_tp typecode_end_tp,
140 std::size_t column_count_tp>
141 requires requires { std::is_enum_v<Typecode_tp>; }
143 public:
146
147 /// Construct a new Row_proxy for rows in a table whose schema is described
148 /// by the given Type_info_t::Row_view_definition_t.
149 ///
150 /// @param row_proxy_definition Description of table definition and packet
151 /// layout. This is an std::array with @c column_count_tp elements, each
152 /// representing a table column. Each element has three members: the typecode
153 /// of the packet where the field value is found; the typecode of the packet
154 /// holding a boolean that indicates whether the value is NULL; and the SQL
155 /// data type. @see Field_view_definition .
157 const typename Type_info_t::Row_view_definition_t &row_proxy_definition)
158 : m_row_proxy_definition(row_proxy_definition) {
159 clear();
160 }
161
162 /// Make the proxy be a view over an "empty" row, which has NULL in all
163 /// nullable fields and 0/"" in non-nullable fields.
164 void clear() { memset(m_field_by_typecode, 0, sizeof(m_field_by_typecode)); }
165
166 /// Make the proxy be a view over the given row.
167 /// @param row Object holding values for all fields in this row.
168 void set_row(const typename Type_info_t::Row_t &row) {
169 clear();
170 for (auto &field : row) {
171 if (field.m_type >= 0 && field.m_type < Type_info_t::typecode_end) {
172 m_field_by_typecode[field.m_type] = &field;
173 }
174 }
175 }
176
177 /// Copy the value of the given field of the current row to the target.
178 /// @param index The column index.
179 /// @param target Opaque pointer (PSI_field *) to the target field.
180 void copy_field(int index, PSI_field *target) const {
181 const auto &def = m_row_proxy_definition[index];
182 bool is_null = false;
183 bool is_empty = false;
184 auto *field = m_field_by_typecode[def.m_field_typecode];
185 // If there is a dedicated "null-ness" field, read that.
186 // (This is a legacy protocol: new protocols should just leave out the
187 // field to indicate that is it is NULL).
188 if (def.m_null_typecode != Type_info_t::typecode_end) {
189 auto *null_field = m_field_by_typecode[def.m_null_typecode];
190 // If null-ness field is missing, don't force it to null.
191 if (null_field != nullptr) {
192 is_empty = is_null = null_field->m_data.m_bool;
193 }
194 }
195 // If the field is missing, make it empty, and in case it is nullable, also
196 // make it null.
197 if (field == nullptr) {
198 is_empty = true;
199 if (def.m_null_typecode != Type_info_t::typecode_end) {
200 is_null = true;
201 }
202 }
203 switch (def.m_type) {
204 /// If more types are needed, see e.g.
205 /// plugin/replication_observers_example/src/binlog/service/iterator/tests/pfs.cc
206 case string_type: {
207 auto *value = is_empty ? "" : field->m_data.m_string;
208 SERVICE_PLACEHOLDER(pfs_plugin_column_string_v2)
209 ->set_char_utf8mb4(target, value, std::strlen(value));
210 break;
211 }
212 case longlong_type: {
213 auto value = is_empty ? 0 : field->m_data.m_int;
214 SERVICE_PLACEHOLDER(pfs_plugin_column_bigint_v1)
215 ->set(target, PSI_longlong{value, is_null});
216 break;
217 }
218 case timestamp_type: {
219 auto value = is_empty ? 0 : field->m_data.m_int;
220 SERVICE_PLACEHOLDER(pfs_plugin_column_timestamp_v2)
221 ->set2(target, value);
222 break;
223 }
224 case enum_type: {
225 unsigned long long value = is_empty ? 0 : field->m_data.m_int;
226 SERVICE_PLACEHOLDER(pfs_plugin_column_enum_v1)
227 ->set(target, PSI_ulonglong{value, is_null});
228 break;
229 }
230 }
231 }
232
233 private:
234 /// Array where the Nth entry is the definition of the Nth column.
236 /// Current map from m_type code to row value
237 const typename Type_info_t::Field_t
239};
240
241#endif // ifndef ROW_PROXY_H
Experimental API header.
Forward declaration.
Definition: row_proxy.h:142
void set_row(const typename Type_info_t::Row_t &row)
Make the proxy be a view over the given row.
Definition: row_proxy.h:168
Row_proxy(const typename Type_info_t::Row_view_definition_t &row_proxy_definition)
Construct a new Row_proxy for rows in a table whose schema is described by the given Type_info_t::Row...
Definition: row_proxy.h:156
void clear()
Make the proxy be a view over an "empty" row, which has NULL in all nullable fields and 0/"" in non-n...
Definition: row_proxy.h:164
void copy_field(int index, PSI_field *target) const
Copy the value of the given field of the current row to the target.
Definition: row_proxy.h:180
const Type_info_t::Row_view_definition_t & m_row_proxy_definition
Array where the Nth entry is the definition of the Nth column.
Definition: row_proxy.h:235
const Type_info_t::Field_t * m_field_by_typecode[Type_info_t::typecode_end]
Current map from m_type code to row value.
Definition: row_proxy.h:238
Ownership-agnostic array class, which is both trivial and standard-layout.
Definition: array_view.h:53
A type code and a value that is either a 64 bit integer, a boolean, or a bounded-length string.
Definition: field.h:48
Specifies macros to define Components.
#define SERVICE_PLACEHOLDER(service)
Use this macro to reference the service placeholder as defined by the REQUIRES_SERVICE_PLACEHOLDER ma...
Definition: component_implementation.h:381
bool is_empty(const std::string &str)
Definition: generic.h:34
bool index(const std::string &value, const String &search_for, uint32_t *idx)
Definition: contains.h:76
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
bool is_null(poly_thread thread, poly_value value)
Definition: jit_executor_type_conversion.cc:46
struct PSI_field PSI_field
This is an opaque structure to denote field in plugin/component code.
Definition: pfs_plugin_table_service.h:93
REQUIRES_SERVICE_PLACEHOLDER(pfs_plugin_column_string_v2)
std::array< Field_view_definition< Typecode_tp, typecode_end_tp >, column_count_tp > Row_view_definition
Description of the mapping between columns and field typecodes, for all columns in a table.
Definition: row_proxy.h:84
Column_type
Framework that helps consuming data in a specific format, typically provided by a service API,...
Definition: row_proxy.h:43
@ timestamp_type
TIMESTAMP, stored in the backend data as microseconds in long long.
Definition: row_proxy.h:49
@ enum_type
ENUM, stored in the backend data as long long.
Definition: row_proxy.h:47
@ longlong_type
BIGINT, stored in the backend data as long long.
Definition: row_proxy.h:45
@ string_type
CHAR(...), stored as a char *.
Definition: row_proxy.h:51
Specifies macros to define Service Implementations.
Description of the mapping between a column and a field typecode.
Definition: row_proxy.h:61
Typecode_tp Typecode_t
Definition: row_proxy.h:62
static constexpr Typecode_t typecode_end
Definition: row_proxy.h:63
Typecode_t m_field_typecode
Enum value for the mysql::abi_helpers::Field object holding the value.
Definition: row_proxy.h:65
Column_type m_type
Type of the field.
Definition: row_proxy.h:67
Typecode_t m_null_typecode
Enum value for a mysql::abi_helpers::Field object that holds a bool indicating if the value is NULL.
Definition: row_proxy.h:75
Definition: pfs_plugin_table_service.h:124
Definition: pfs_plugin_table_service.h:130
Aggregates type definitions and constants for a given typecode enum, end element of that enum,...
Definition: row_proxy.h:96
Row_view_definition< Typecode_t, typecode_end, column_count > Row_view_definition_t
Definition: row_proxy.h:104
static constexpr std::size_t column_count
Definition: row_proxy.h:99
static constexpr Typecode_t typecode_end
Definition: row_proxy.h:98
Typecode_tp Typecode_t
Definition: row_proxy.h:97
std::string string_type
Definition: validate_password_imp.cc:85