MySQL 9.1.0
Source Code Documentation
json_diff.h
Go to the documentation of this file.
1#ifndef JSON_DIFF_INCLUDED
2#define JSON_DIFF_INCLUDED
3
4/* Copyright (c) 2017, 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 Header file for the Json_diff class.
31
32 The Json_diff class is used to represent a logical change in a JSON column,
33 so that a replication master can send only what has changed, instead of
34 sending the whole new value to the replication slave when a JSON column is
35 updated.
36*/
37
38#include <stddef.h>
39#include <algorithm>
40#include <memory> // std::unique_ptr
41#include <optional>
42#include <vector>
43
46
47class Json_dom;
48class Json_wrapper;
49class String;
50
51/// Enum that describes what kind of operation a Json_diff object represents.
53 /**
54 The JSON value in the given path is replaced with a new value.
55 It has the same effect as `JSON_REPLACE(col, path, value)`.
56 */
57 REPLACE,
58
59 /**
60 Add a new element at the given path.
61
62 If the path specifies an array element, it has the same effect as
63 `JSON_ARRAY_INSERT(col, path, value)`.
64
65 If the path specifies an object member, it has the same effect as
66 `JSON_INSERT(col, path, value)`.
67 */
68 INSERT,
69
70 /**
71 The JSON value at the given path is removed from an array or object.
72 It has the same effect as `JSON_REMOVE(col, path)`.
73 */
74 REMOVE,
75};
76/// The number of elements of the enumeration above.
77static const int JSON_DIFF_OPERATION_COUNT = 3;
78
79/**
80 A class that represents a logical change to a JSON document. It is used by
81 row-based replication to send information about changes in JSON documents
82 without sending the whole updated document.
83*/
84class Json_diff final {
85 /// The path that is changed.
87 /// The operation to perform on the changed path.
89 /// The new value to add to the changed path.
90 std::unique_ptr<Json_dom> m_value;
91
92 /// The length of the operation when encoded in binary format.
93 static const size_t ENCODED_OPERATION_BYTES = 1;
94
95 public:
96 /**
97 Construct a Json_diff object.
98
99 @param path the path that is changed
100 @param operation the operation to perform on the path
101 @param value the new value in the path (the Json_diff object
102 takes over the ownership of the value)
103 */
105 std::unique_ptr<Json_dom> value);
106
108 Json_diff(Json_diff &&) noexcept = default;
109 Json_diff &operator=(Json_diff &&) noexcept = default;
110 Json_diff(const Json_diff &) = delete;
111 Json_diff &operator=(const Json_diff &) = delete;
112
113 /// Get the path that is changed by this diff.
114 const Json_path &path() const { return m_path; }
115
116 /// Get the operation that is performed on the path.
118
119 /**
120 Get a Json_wrapper representing the new value to add to the path. The
121 wrapper is an alias, so the ownership of the contained Json_dom is retained
122 by the Json_diff object.
123 @see Json_wrapper::set_alias()
124 */
125 Json_wrapper value() const;
126
127 size_t binary_length() const;
128 /**
129 Serialize this Json_diff object and append to the given string
130
131 @param to The String to append to
132 @retval false Success
133 @retval true Failure, meaning out of memory
134 */
135 bool write_binary(String *to) const;
136};
137
138/**
139 Vector of logical diffs describing changes to a JSON column.
140*/
142 public:
143 /// Type of the allocator for the underlying invector.
145 /// Type of the underlying vector
146 typedef std::vector<Json_diff, allocator_type> vector;
147 /// Type of iterator over the underlying vector
148 typedef vector::iterator iterator;
149 /// Type of iterator over the underlying vector
150 typedef vector::const_iterator const_iterator;
151 /**
152 Constructor
153 @param arg Mem_root_allocator to use for the vector
154 */
155 explicit Json_diff_vector(allocator_type arg);
156 /**
157 Append a new diff at the end of this vector.
158 @param diff The diff to add.
159 */
160 void add_diff(Json_diff diff);
161 /**
162 Append a new diff at the end of this vector.
163 @param path Path to update
164 @param operation Operation
165 @param dom New value to insert
166 */
167 void add_diff(const Json_seekable_path &path,
168 enum_json_diff_operation operation,
169 std::unique_ptr<Json_dom> dom);
170 /**
171 Append a new diff at the end of this vector when operation == REMOVE.
172 @param path Path to update
173 @param operation Operation
174 */
175 void add_diff(const Json_seekable_path &path,
176 enum_json_diff_operation operation);
177 /// Clear the vector.
178 void clear();
179 /// Return the number of elements in the vector.
180 inline size_t size() const { return m_vector.size(); }
181
182 /**
183 Return the element at the given position
184 @param pos Position
185 @return the pos'th element
186 */
187 inline Json_diff &at(size_t pos) { return m_vector.at(pos); }
188
189 // Return forward iterator to the beginning
190 inline const_iterator begin() const { return m_vector.begin(); }
191
192 // Return forward iterator to the end
193 const_iterator end() const { return m_vector.end(); }
194
195 /**
196 Return the length of the binary representation of this
197 Json_diff_vector.
198
199 The binary format has this form:
200
201 +--------+--------+--------+ +--------+
202 | length | diff_1 | diff_2 | ... | diff_N |
203 +--------+--------+--------+ +--------+
204
205 This function returns the length of only the diffs, if
206 include_metadata==false. It returns the length of the 'length'
207 field plus the length of the diffs, if include_metadata=true. The
208 value of the 'length' field is exactly the return value from this
209 function when include_metadata=false.
210
211 @param include_metadata if true, include the length of the length
212 field in the computation, otherwise don't.
213
214 @return The computed length
215 */
216 size_t binary_length(bool include_metadata = true) const;
217
218 /**
219 Serialize this Json_diff_vector into the given String.
220
221 @param to String to which the vector will be appended
222
223 @retval false Success
224 @retval true Failure (out of memory)
225 */
226 bool write_binary(String *to) const;
227
228 /**
229 De-serialize Json_diff objects from the given String into this
230 Json_diff_vector.
231
232 @param[in,out] from Pointer to buffer to read from. The function
233 will move this to point to the next byte to read after those that
234 were read.
235
236 @param[in] table Table structure (used for error messages).
237
238 @param[in] field_name Field name (used for error messages).
239
240 @retval false Success
241 @retval true Failure (bad format or out of memory)
242 */
243 bool read_binary(const char **from, const struct TABLE *table,
244 const char *field_name);
245
246 /// An empty diff vector (having no diffs).
248
249 private:
250 // The underlying vector
252
253 /// Length in bytes of the binary representation, not counting the 4 bytes
254 /// length
256
257 /// The length of the field where the total length is encoded.
258 static const size_t ENCODED_LENGTH_BYTES = 4;
259};
260
261/**
262 The result of applying JSON diffs on a JSON value using apply_json_diff().
263*/
265 /**
266 The JSON diffs were applied and the JSON value in the column was updated
267 successfully.
268 */
269 SUCCESS,
270
271 /**
272 An error was raised while applying one of the diffs. The value in the
273 column was not updated.
274 */
275 ERROR,
276
277 /**
278 One of the diffs was rejected. This could happen if the path specified in
279 the diff does not exist in the JSON value, or if the diff is supposed to
280 add a new value at a given path, but there already is a value at the path.
281
282 This return code would usually indicate that the replication slave where
283 the diff is applied, is out of sync with the replication master where the
284 diff was created.
285
286 The value in the column was not updated, but no error was raised.
287 */
288 REJECTED,
289};
290
291/**
292 Apply one JSON diff to the DOM provided.
293
294 @param diff The diff which contains the path to apply it and the new value.
295 @param dom The DOM to apply the diff to.
296 @return An enum_json_diff_status value that tells if the diff was applied
297 successfully.
298 */
300
301/// The result of a call to read_json_diff().
303 /// The JSON diff that was read from the buffer.
305 /// The number of bytes read from the buffer.
307};
308
309/**
310 Read one JSON diff from a buffer.
311
312 @param pos The position to start reading from in the buffer. When the function
313 returns, it will be set to the position right after the last byte read.
314 @param length The maximum number of bytes to read from the buffer.
315
316 @return An object containing the Json_diff value and the number of bytes read,
317 if successful. An empty value if an error was raised, or if the buffer did not
318 contain a valid diff.
319 */
320std::optional<ReadJsonDiffResult> read_json_diff(const unsigned char *pos,
321 size_t length);
322
323#endif /* JSON_DIFF_INCLUDED */
Vector of logical diffs describing changes to a JSON column.
Definition: json_diff.h:141
std::vector< Json_diff, allocator_type > vector
Type of the underlying vector.
Definition: json_diff.h:146
size_t m_binary_length
Length in bytes of the binary representation, not counting the 4 bytes length.
Definition: json_diff.h:255
vector::iterator iterator
Type of iterator over the underlying vector.
Definition: json_diff.h:148
const_iterator end() const
Definition: json_diff.h:193
static const size_t ENCODED_LENGTH_BYTES
The length of the field where the total length is encoded.
Definition: json_diff.h:258
void add_diff(Json_diff diff)
Append a new diff at the end of this vector.
Definition: json_diff.cc:269
size_t binary_length(bool include_metadata=true) const
Return the length of the binary representation of this Json_diff_vector.
Definition: json_diff.cc:290
Mem_root_allocator< Json_diff > allocator_type
Type of the allocator for the underlying invector.
Definition: json_diff.h:144
size_t size() const
Return the number of elements in the vector.
Definition: json_diff.h:180
vector::const_iterator const_iterator
Type of iterator over the underlying vector.
Definition: json_diff.h:150
Json_diff_vector(allocator_type arg)
Constructor.
Definition: json_diff.cc:261
const_iterator begin() const
Definition: json_diff.h:190
Json_diff & at(size_t pos)
Return the element at the given position.
Definition: json_diff.h:187
vector m_vector
Definition: json_diff.h:251
bool write_binary(String *to) const
Serialize this Json_diff_vector into the given String.
Definition: json_diff.cc:294
static const Json_diff_vector EMPTY_JSON_DIFF_VECTOR
An empty diff vector (having no diffs).
Definition: json_diff.h:247
void clear()
Clear the vector.
Definition: json_diff.cc:285
bool read_binary(const char **from, const struct TABLE *table, const char *field_name)
De-serialize Json_diff objects from the given String into this Json_diff_vector.
Definition: json_diff.cc:316
A class that represents a logical change to a JSON document.
Definition: json_diff.h:84
size_t binary_length() const
Definition: json_diff.cc:126
Json_wrapper value() const
Get a Json_wrapper representing the new value to add to the path.
Definition: json_diff.cc:69
static const size_t ENCODED_OPERATION_BYTES
The length of the operation when encoded in binary format.
Definition: json_diff.h:93
const Json_path & path() const
Get the path that is changed by this diff.
Definition: json_diff.h:114
std::unique_ptr< Json_dom > m_value
The new value to add to the changed path.
Definition: json_diff.h:90
Json_path m_path
The path that is changed.
Definition: json_diff.h:86
bool write_binary(String *to) const
Serialize this Json_diff object and append to the given string.
Definition: json_diff.cc:172
enum_json_diff_operation m_operation
The operation to perform on the changed path.
Definition: json_diff.h:88
enum_json_diff_operation operation() const
Get the operation that is performed on the path.
Definition: json_diff.h:117
Json_diff(Json_diff &&) noexcept=default
Json_diff(const Json_seekable_path &path, enum_json_diff_operation operation, std::unique_ptr< Json_dom > value)
Construct a Json_diff object.
Definition: json_diff.cc:58
JSON DOM abstract base class.
Definition: json_dom.h:172
A JSON path expression.
Definition: json_path.h:350
A path expression which can be used to seek to a position inside a JSON value.
Definition: json_path.h:295
Abstraction for accessing JSON values irrespective of whether they are (started out as) binary JSON v...
Definition: json_dom.h:1150
Mem_root_allocator is a C++ STL memory allocator based on MEM_ROOT.
Definition: mem_root_allocator.h:68
Using this class is fraught with peril, and you need to be very careful when doing so.
Definition: sql_string.h:167
static Bigint * diff(Bigint *a, Bigint *b, Stack_alloc *alloc)
Definition: dtoa.cc:1081
enum_json_diff_status apply_json_diff(const Json_diff &diff, Json_dom *dom)
Apply one JSON diff to the DOM provided.
Definition: json_diff.cc:455
enum_json_diff_status
The result of applying JSON diffs on a JSON value using apply_json_diff().
Definition: json_diff.h:264
@ REJECTED
One of the diffs was rejected.
@ ERROR
An error was raised while applying one of the diffs.
@ SUCCESS
The JSON diffs were applied and the JSON value in the column was updated successfully.
std::optional< ReadJsonDiffResult > read_json_diff(const unsigned char *pos, size_t length)
Read one JSON diff from a buffer.
Definition: json_diff.cc:358
enum_json_diff_operation
Enum that describes what kind of operation a Json_diff object represents.
Definition: json_diff.h:52
@ REPLACE
The JSON value in the given path is replaced with a new value.
@ INSERT
Add a new element at the given path.
@ REMOVE
The JSON value at the given path is removed from an array or object.
static const int JSON_DIFF_OPERATION_COUNT
The number of elements of the enumeration above.
Definition: json_diff.h:77
This file contains interface support for the JSON path abstraction.
static char * path
Definition: mysqldump.cc:149
static PFS_engine_table_share_proxy table
Definition: pfs.cc:61
bool length(const dd::Spatial_reference_system *srs, const Geometry *g1, double *length, bool *null) noexcept
Computes the length of linestrings and multilinestrings.
Definition: length.cc:76
The result of a call to read_json_diff().
Definition: json_diff.h:302
Json_diff diff
The JSON diff that was read from the buffer.
Definition: json_diff.h:304
size_t bytes_read
The number of bytes read from the buffer.
Definition: json_diff.h:306
Definition: table.h:1421