MySQL 8.0.32
Source Code Documentation
rpl_record.h
Go to the documentation of this file.
1/* Copyright (c) 2007, 2022, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23#ifndef RPL_RECORD_H
24#define RPL_RECORD_H
25
26#include <stddef.h>
27#include <sys/types.h>
28
29#include "my_inttypes.h"
30
31class Relay_log_info;
32struct TABLE;
33
34struct MY_BITMAP;
35
36class table_def;
37class Bit_reader;
38
40
41#if defined(MYSQL_SERVER)
42size_t pack_row(TABLE *table, MY_BITMAP const *cols, uchar *row_data,
43 const uchar *data, enum_row_image_type row_image_type,
44 ulonglong value_options = 0);
45
46/**
47 Unpack a row image (either before-image or after-image) into @c
48 table->record[0].
49
50 The row is assumed to only consist of the fields for which the
51 corresponding bit in bitset @c column_image is set; the other parts
52 of the record are left alone.
53
54 If the replica table has more columns than the source table, then the
55 extra columns are not touched by this function. If the source table
56 has more columns than the replica table, then the position is moved to
57 after the extra columns, but the values are not used.
58
59 If the replica has a GIPK and the source does not, then the extra column
60 is not touched by this function. If the source table has a GIPK and the
61 replica does not, then the position is shifted forward by 1.
62
63 - The layout of a row is:
64
65 For WRITE_ROWS_EVENT:
66 +--------------+
67 | after-image |
68 +--------------+
69
70 For DELETE_ROWS_EVENT:
71 +--------------+
72 | before-image |
73 +--------------+
74
75 For UPDATE_ROWS_EVENT:
76 +--------------+-------------+
77 | before-image | after-image |
78 +--------------+-------------+
79
80 For PARTIAL_UPDATE_ROWS_EVENT:
81 +--------------+--------------+-------------+
82 | before-image | shared-image | after-image |
83 +--------------+--------------+-------------+
84
85 - Each of before-image and after-image has the following format:
86 +--------+-------+-------+ +-------+
87 | length | col_1 | col_2 | ... | col_N |
88 +--------+-------+-------+ +-------+
89 length is a 4-byte integer in little-endian format, equal to the
90 total length in bytes of col_1, col_2, ..., col_N.
91
92 - The shared-image has one of the following formats:
93 +-----------------+
94 | value_options=0 |
95 +-----------------+
96 or
97 +-----------------+--------------+
98 | value_options=1 | partial_bits |
99 +-----------------+--------------+
100 where:
101
102 - value_options is a bitmap, stored as an integer, in the format
103 of net_field_length. Currently only one bit is allowed:
104 1=PARTIAL_JSON_UPDATES (so therefore the integer is always 0 or
105 1, so in reality value_options is only one byte). When
106 PARTIAL_JSON_UPDATES=0, there is nothing else in the
107 shared-image. When PARTIAL_JSON_UPDATES=1, there is a
108 partial_bits field.
109
110 - partial_bits has one bit for each *JSON* column in the table
111 (regardless of whether it is included in the before-image and/or
112 after-image). The bit is 0 if the JSON update is stored as a
113 full document in the after-image, and 1 if the JSON update in
114 partial form in the after-image.
115
116 - Both when reading the before-image and when reading the
117 after-image it is necessary to know the partialness of JSON
118 columns: when reading the before-image, before looking up the
119 row in the table, we need to set the column in the table's
120 'read_set' (even if the column was not in the before-image), in
121 order to guarantee that the storage engine reads that column, so
122 that there is any base document that the diff can be applied
123 on. When reading the after-image, we need to know which columns
124 are partial so that we can correctly parse the data for that
125 column.
126
127 Therefore, when this function parses the before-image of a
128 PARTIAL_UPDATE_ROWS_LOG_EVENT, it reads both the before-image
129 and the shared-image, but leaves the read position after the
130 before-image. So when it parses the after-image of a
131 PARTIAL_UPDATE_ROWS_LOG_EVENT, the read position is at the
132 beginning of the shared-image, so it parses both the
133 shared-image and the after-image.
134
135 @param[in] rli Applier execution context
136
137 @param[in,out] table Table to unpack into
138
139 @param[in] source_column_count Number of columns that the source had
140 in its table
141
142 @param[in] row_data Beginning of the row image
143
144 @param[in] column_image Pointer to a bit vector where the N'th bit
145 is 0 for columns that are not included in the event, and 1 for
146 columns that are included in the event.
147
148 @param[out] row_image_end_p If this function returns successfully, it
149 sets row_image_end to point to the next byte after the row image
150 that it has read.
151
152 @param[in] event_end Pointer to the end of the event.
153
154 @param[in] row_image_type The type of row image that we are going to
155 read: WRITE_AI, UPDATE_BI, UPDATE_AI, or DELETE_BI.
156
157 @param[in] event_has_value_options true for PARTIAL_UPDATE_ROWS_EVENT,
158 false for UPDATE_ROWS_EVENT.
159
160 @param only_seek If true, this is a seek operation rather than a
161 read operation. It will only compute the row_image_end_p pointer,
162 and not read anything into the table and not apply any JSON diffs.
163 (This is used in slave_rows_search_algorithms=HASH_SCAN, which (1)
164 unpacks and hashes the before-image for all rows in the event, (2)
165 scans the table, and for each matching row it (3) unpacks the
166 after-image and applies on the table. In step (1) it needs to unpack
167 the after-image too, in order to move the read position forwards,
168 and then it should use only_seek=true. This is an optimization, but
169 more importantly, when the after-image contains partial JSON, the
170 partial JSON cannot be applied in step (1) since there is no JSON
171 document to apply it on.)
172
173 @returns false on success, true on error.
174 */
175bool unpack_row(Relay_log_info const *rli, TABLE *table,
176 uint const source_column_count, uchar const *const row_data,
177 MY_BITMAP const *column_image,
178 uchar const **const row_image_end_p,
179 uchar const *const event_end,
180 enum_row_image_type row_image_type,
181 bool event_has_value_options, bool only_seek);
182
183/**
184 Return a pointer within a row event's row data, to the data of the first
185 column that exists on the replica.
186
187 This skips the 'null bits' field, which precedes the column definitions in the
188 row image. In case a GIPK exists in the event but not in this replica's table
189 definition, it skips the GIPK too.
190
191 @param raw_data The data received from the source
192 @param column_image The column bitmap
193 @param column_count The number of column in the image bitmap
194 @param null_bits The bits that are null
195 @param tabledef The source table definition structure
196 @param source_has_gipk If the source table has a GIPK
197 @param replica_has_gipk If the replica table has a GIPK
198
199 @return const uchar* The adjusted point to the source data
200 */
202 const uchar *raw_data, MY_BITMAP const *column_image, size_t column_count,
203 Bit_reader &null_bits, table_def *tabledef, bool source_has_gipk,
204 bool replica_has_gipk);
205
206// Fill table's record[0] with default values.
207int prepare_record(TABLE *const table, const MY_BITMAP *cols, const bool check);
208#endif
209
210/**
211 Template base class of Bit_reader / Bit_writer.
212*/
213template <typename T, typename UT>
215 protected:
216 /// Pointer to beginning of buffer where bits are read or written.
218 /// Current position in buffer.
220
221 public:
222 /**
223 Construct a new Bit_stream (either reader or writer).
224 @param ptr Pointer where bits will be read or written.
225 */
226 Bit_stream_base(T *ptr) : m_ptr(ptr), m_current_bit(0) {}
227
228 /**
229 Set the buffer pointer.
230 @param ptr Pointer where bits will be read or written.
231 */
232 void set_ptr(T *ptr) { m_ptr = ptr; }
233 /**
234 Set the buffer pointer, using an unsigned datatype.
235 @param ptr Pointer where bits will be read or written.
236 */
237 void set_ptr(UT *ptr) { m_ptr = (T *)ptr; }
238
239 /// @return the current position.
240 uint tell() const { return m_current_bit; }
241
242 /**
243 Print all the bits before the current position to the debug trace.
244 @param str Descriptive text that will be prefixed before the bit string.
245 */
246 void dbug_print(const char *str [[maybe_unused]]) const;
247};
248
249/**
250 Auxiliary class to write a stream of bits to a memory location.
251
252 Call set() to write a bit and move the position one bit forward.
253*/
254class Bit_writer : public Bit_stream_base<char, uchar> {
255 public:
256 Bit_writer(char *ptr = nullptr) : Bit_stream_base<char, uchar>(ptr) {}
257 Bit_writer(uchar *ptr) : Bit_writer((char *)ptr) {}
258
259 /**
260 Write the next bit and move the write position one bit forward.
261 @param set_to_on If true, set the bit to 1, otherwise set it to 0.
262 */
263 void set(bool set_to_on) {
264 uint byte = m_current_bit / 8;
265 uint bit_within_byte = m_current_bit % 8;
267 if (bit_within_byte == 0)
268 m_ptr[byte] = set_to_on ? 1 : 0;
269 else if (set_to_on)
270 m_ptr[byte] |= 1 << bit_within_byte;
271 }
272};
273
274/**
275 Auxiliary class to read or write a stream of bits to a memory location.
276
277 Call get() to read a bit and move the position one bit forward.
278*/
279class Bit_reader : public Bit_stream_base<const char, const uchar> {
280 public:
281 Bit_reader(const char *ptr = nullptr)
282 : Bit_stream_base<const char, const uchar>(ptr) {}
283 Bit_reader(const uchar *ptr) : Bit_reader((const char *)ptr) {}
284
285 /**
286 Read the next bit and move the read position one bit forward.
287 @return true if the bit was 1, false if the bit was 0.
288 */
289 bool get() {
290 uint byte = m_current_bit / 8;
291 uint bit_within_byte = m_current_bit % 8;
293 return (m_ptr[byte] & (1 << bit_within_byte)) != 0;
294 }
295};
296
297#endif // ifdef RPL_RECORD_H
Auxiliary class to read or write a stream of bits to a memory location.
Definition: rpl_record.h:279
bool get()
Read the next bit and move the read position one bit forward.
Definition: rpl_record.h:289
Bit_reader(const uchar *ptr)
Definition: rpl_record.h:283
Bit_reader(const char *ptr=nullptr)
Definition: rpl_record.h:281
Template base class of Bit_reader / Bit_writer.
Definition: rpl_record.h:214
T * m_ptr
Pointer to beginning of buffer where bits are read or written.
Definition: rpl_record.h:217
uint m_current_bit
Current position in buffer.
Definition: rpl_record.h:219
uint tell() const
Definition: rpl_record.h:240
void set_ptr(UT *ptr)
Set the buffer pointer, using an unsigned datatype.
Definition: rpl_record.h:237
void set_ptr(T *ptr)
Set the buffer pointer.
Definition: rpl_record.h:232
void dbug_print(const char *str) const
Print all the bits before the current position to the debug trace.
Definition: rpl_record.cc:61
Bit_stream_base(T *ptr)
Construct a new Bit_stream (either reader or writer).
Definition: rpl_record.h:226
Auxiliary class to write a stream of bits to a memory location.
Definition: rpl_record.h:254
void set(bool set_to_on)
Write the next bit and move the write position one bit forward.
Definition: rpl_record.h:263
Bit_writer(uchar *ptr)
Definition: rpl_record.h:257
Bit_writer(char *ptr=nullptr)
Definition: rpl_record.h:256
Definition: rpl_rli.h:201
A table definition from the master.
Definition: rpl_utility.h:247
unsigned char byte
Blob class.
Definition: common.h:150
Some integer typedefs for easier portability.
unsigned long long int ulonglong
Definition: my_inttypes.h:55
unsigned char uchar
Definition: my_inttypes.h:51
std::string str(const mysqlrouter::ConfigGenerator::Options::Endpoint &ep)
Definition: config_generator.cc:1063
enum_row_image_type
Definition: rpl_record.h:39
const uchar * translate_beginning_of_raw_data(const uchar *raw_data, MY_BITMAP const *column_image, size_t column_count, Bit_reader &null_bits, table_def *tabledef, bool source_has_gipk, bool replica_has_gipk)
Return a pointer within a row event's row data, to the data of the first column that exists on the re...
Definition: rpl_record.cc:780
bool unpack_row(Relay_log_info const *rli, TABLE *table, uint const source_column_count, uchar const *const row_data, MY_BITMAP const *column_image, uchar const **const row_image_end_p, uchar const *const event_end, enum_row_image_type row_image_type, bool event_has_value_options, bool only_seek)
Unpack a row image (either before-image or after-image) into table->record[0].
Definition: rpl_record.cc:447
int prepare_record(TABLE *const table, const MY_BITMAP *cols, const bool check)
Fills table->record[0] with default values.
Definition: rpl_record.cc:810
size_t pack_row(TABLE *table, MY_BITMAP const *cols, uchar *row_data, const uchar *data, enum_row_image_type row_image_type, ulonglong value_options=0)
Pack a record of data for a table into a format suitable for the binary log.
Definition: rpl_record.cc:269
Definition: my_bitmap.h:42
Definition: table.h:1395
unsigned int uint
Definition: uca-dump.cc:29