MySQL 8.0.37
Source Code Documentation
json_binary.h
Go to the documentation of this file.
1#ifndef JSON_BINARY_INCLUDED
2#define JSON_BINARY_INCLUDED
3
4/* Copyright (c) 2015, 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 This file specifies the interface for serializing JSON values into
31 binary representation, and for reading values back from the binary
32 representation.
33
34 The binary format is as follows:
35
36 Each JSON value (scalar, object or array) has a one byte type
37 identifier followed by the actual value.
38
39 If the value is a JSON object, its binary representation will have a
40 header that contains:
41
42 - the member count
43 - the size of the binary value in bytes
44 - a list of pointers to each key
45 - a list of pointers to each value
46
47 The actual keys and values will come after the header, in the same
48 order as in the header.
49
50 Similarly, if the value is a JSON array, the binary representation
51 will have a header with
52
53 - the element count
54 - the size of the binary value in bytes
55 - a list of pointers to each value
56
57 followed by the actual values, in the same order as in the header.
58
59 @verbatim
60 doc ::= type value
61
62 type ::=
63 0x00 | // small JSON object
64 0x01 | // large JSON object
65 0x02 | // small JSON array
66 0x03 | // large JSON array
67 0x04 | // literal (true/false/null)
68 0x05 | // int16
69 0x06 | // uint16
70 0x07 | // int32
71 0x08 | // uint32
72 0x09 | // int64
73 0x0a | // uint64
74 0x0b | // double
75 0x0c | // utf8mb4 string
76 0x0f // custom data (any MySQL data type)
77
78 value ::=
79 object |
80 array |
81 literal |
82 number |
83 string |
84 custom-data
85
86 object ::= element-count size key-entry* value-entry* key* value*
87
88 array ::= element-count size value-entry* value*
89
90 // number of members in object or number of elements in array
91 element-count ::=
92 uint16 | // if used in small JSON object/array
93 uint32 // if used in large JSON object/array
94
95 // number of bytes in the binary representation of the object or array
96 size ::=
97 uint16 | // if used in small JSON object/array
98 uint32 // if used in large JSON object/array
99
100 key-entry ::= key-offset key-length
101
102 key-offset ::=
103 uint16 | // if used in small JSON object
104 uint32 // if used in large JSON object
105
106 key-length ::= uint16 // key length must be less than 64KB
107
108 value-entry ::= type offset-or-inlined-value
109
110 // This field holds either the offset to where the value is stored,
111 // or the value itself if it is small enough to be inlined (that is,
112 // if it is a JSON literal or a small enough [u]int).
113 offset-or-inlined-value ::=
114 uint16 | // if used in small JSON object/array
115 uint32 // if used in large JSON object/array
116
117 key ::= utf8mb4-data
118
119 literal ::=
120 0x00 | // JSON null literal
121 0x01 | // JSON true literal
122 0x02 | // JSON false literal
123
124 number ::= .... // little-endian format for [u]int(16|32|64), whereas
125 // double is stored in a platform-independent, eight-byte
126 // format using float8store()
127
128 string ::= data-length utf8mb4-data
129
130 custom-data ::= custom-type data-length binary-data
131
132 custom-type ::= uint8 // type identifier that matches the
133 // internal enum_field_types enum
134
135 data-length ::= uint8* // If the high bit of a byte is 1, the length
136 // field is continued in the next byte,
137 // otherwise it is the last byte of the length
138 // field. So we need 1 byte to represent
139 // lengths up to 127, 2 bytes to represent
140 // lengths up to 16383, and so on...
141 @endverbatim
142*/
143
144#include <stddef.h>
145#include <cassert>
146#include <cstdint>
147#include <functional>
148#include <string>
149
150/*
151 This file is part of our public interface for the 'json_binary' library.
152 This means that #includes of MySQL headers here should be limited to
153 files that are INSTALLed.
154*/
155#include "field_types.h" // enum_field_types
157
158#ifdef MYSQL_SERVER
159class Field_json;
160class Json_dom;
161class Json_wrapper;
162class THD;
163#endif
164
165class String;
166
167#if defined(WIN32) && defined(EXPORT_JSON_FUNCTIONS)
168#define EXPORT_JSON_FUNCTION __declspec(dllexport)
169#else
170#define EXPORT_JSON_FUNCTION
171#endif
172
173namespace json_binary {
174
175/**
176 Serialize the JSON document represented by dom to binary format in
177 the destination string, replacing any content already in the
178 destination string.
179
180 @param[in] thd THD handle
181 @param[in] dom the input DOM tree
182 @param[in,out] dest the destination string
183 @retval false on success
184 @retval true if an error occurred
185*/
186#ifdef MYSQL_SERVER
187bool serialize(const THD *thd, const Json_dom *dom, String *dest);
188#endif
189
190/**
191 Class used for reading JSON values that are stored in the binary
192 format. Values are parsed lazily, so that only the parts of the
193 value that are interesting to the caller, are read. Array elements
194 can be looked up in constant time using the element() function.
195 Object members can be looked up in O(log n) time using the lookup()
196 function.
197*/
198class Value {
199 public:
200 enum enum_type : uint8_t {
211 ERROR /* Not really a type. Used to signal that an
212 error was detected. */
213 };
214
215 /**
216 Does this value, and all of its members, represent a valid JSON
217 value?
218 */
220 bool is_valid() const;
221
223 enum_type type() const { return m_type; }
224
225 /// Does this value use the large storage format?
227 bool large_format() const { return m_large; }
228
229 /**
230 Get a pointer to the beginning of the STRING or OPAQUE data
231 represented by this instance.
232 */
234 const char *get_data() const {
235 assert(m_type == STRING || m_type == OPAQUE);
236 return m_data;
237 }
238
239 /**
240 Get the length in bytes of the STRING or OPAQUE value represented by
241 this instance.
242 */
244 uint32_t get_data_length() const {
245 assert(m_type == STRING || m_type == OPAQUE);
246 return m_length;
247 }
248
249 /** Get the value of an INT. */
251 int64_t get_int64() const {
252 assert(m_type == INT);
253 return m_int_value;
254 }
255
256 /** Get the value of a UINT. */
258 uint64_t get_uint64() const {
259 assert(m_type == UINT);
260 return static_cast<uint64_t>(m_int_value);
261 }
262
263 /** Get the value of a DOUBLE. */
265 double get_double() const {
266 assert(m_type == DOUBLE);
267 return m_double_value;
268 }
269
270 /**
271 Get the number of elements in an array, or the number of members in
272 an object.
273 */
275 uint32_t element_count() const {
276 assert(m_type == ARRAY || m_type == OBJECT);
277 return m_element_count;
278 }
279
280 /**
281 Get the MySQL field type of an opaque value. Identifies the type of
282 the value stored in the data portion of an opaque value.
283 */
286 assert(m_type == OPAQUE);
287 return m_field_type;
288 }
289
291 Value element(size_t pos) const;
292
294 Value key(size_t pos) const;
295
297 Value lookup(const char *key, size_t length) const;
298
300 Value lookup(const std::string &key) const {
301 return lookup(key.c_str(), key.length());
302 }
303
305 size_t lookup_index(const char *key, size_t length) const;
306
308 size_t lookup_index(const std::string &key) const {
309 return lookup_index(key.c_str(), key.length());
310 }
311
313 bool is_backed_by(const String *str) const;
314
315#ifdef MYSQL_SERVER
316 bool raw_binary(const THD *thd, String *buf) const;
317 bool get_free_space(const THD *thd, size_t *space) const;
318 bool update_in_shadow(const Field_json *field, size_t pos,
319 Json_wrapper *new_value, size_t data_offset,
320 size_t data_length, const char *original,
321 char *destination, bool *changed) const;
322 bool remove_in_shadow(const Field_json *field, size_t pos,
323 const char *original, char *destination) const;
324#endif
326 bool has_space(size_t pos, size_t needed, size_t *offset) const;
327
328 /** Constructor for values that represent literals or errors. */
330 explicit Value(enum_type t) : m_data(nullptr), m_type(t) {
331 assert(t == LITERAL_NULL || t == LITERAL_TRUE || t == LITERAL_FALSE ||
332 t == ERROR);
333 }
334
335 /** Constructor for values that represent ints or uints. */
337 explicit Value(enum_type t, int64_t val) : m_int_value(val), m_type(t) {
338 assert(t == INT || t == UINT);
339 }
340
341 /** Constructor for values that represent doubles. */
343 explicit Value(double val) : m_double_value(val), m_type(DOUBLE) {}
344
345 /** Constructor for values that represent strings. */
347 Value(const char *data, uint32_t len)
348 : m_data(data), m_length(len), m_type(STRING) {}
349
350 /**
351 Constructor for values that represent arrays or objects.
352
353 @param t type
354 @param data pointer to the start of the binary representation
355 @param bytes the number of bytes in the binary representation of the value
356 @param element_count the number of elements or members in the value
357 @param large true if the value should be stored in the large
358 storage format with 4 byte offsets instead of 2 byte offsets
359 */
361 Value(enum_type t, const char *data, uint32_t bytes, uint32_t element_count,
362 bool large)
363 : m_data(data),
365 m_length(bytes),
366 m_type(t),
367 m_large(large) {
368 assert(t == ARRAY || t == OBJECT);
369 }
370
371 /** Constructor for values that represent opaque data. */
373 Value(enum_field_types ft, const char *data, uint32_t len)
374 : m_data(data), m_length(len), m_field_type(ft), m_type(OPAQUE) {}
375
376 /** Empty constructor. Produces a value that represents an error condition. */
379
380 /** Is this value an array? */
382 bool is_array() const { return m_type == ARRAY; }
383
384 /** Is this value an object? */
386 bool is_object() const { return m_type == OBJECT; }
387
388 /**
389 Format the JSON value to an external JSON string in buffer in
390 the format of ISO/IEC 10646.
391
392 @param[in,out] buffer the formatted string is appended, so make sure
393 the length is set correctly before calling
394 @param[in] depth_handler Pointer to a function that should handle error
395 occurred when depth is exceeded.
396
397 @return false formatting went well, else true
398 */
400 bool to_std_string(std::string *buffer,
401 const JsonDocumentDepthHandler &depth_handler) const;
402
403 /**
404 Format the JSON value to an external JSON string in buffer in the format of
405 ISO/IEC 10646. Add newlines and indentation for readability.
406
407 @param[in,out] buffer the buffer that receives the formatted string
408 (the string is appended, so make sure the length
409 is set correctly before calling)
410 @param[in] depth_handler Pointer to a function that should handle error
411 occurred when depth is exceeded.
412
413 @retval false on success
414 @retval true on error
415 */
418 std::string *buffer, const JsonDocumentDepthHandler &depth_handler) const;
419
420 /**
421 Compare two Values
422 @note This function is limited to scalars only, for objects/arrays it
423 asserts. The main purpose is to separate old/new scalar values for updates
424 on multi-valued indexes.
425 @returns
426 -1 this < val
427 0 this == val
428 1 this > val
429 */
430#ifdef MYSQL_SERVER
431 int eq(const Value &val) const;
432#endif
433
434 private:
435 /*
436 Instances use only one of m_data, m_int_value and m_double_value,
437 so keep them in a union to save space in memory.
438 */
439 union {
440 /**
441 Pointer to the start of the binary representation of the value. Only
442 used by STRING, OPAQUE, OBJECT and ARRAY.
443
444 The memory pointed to by this member is not owned by this Value
445 object. Callers that create Value objects must make sure that the
446 memory is not freed as long as the Value object is alive.
447 */
448 const char *m_data;
449 /** The value if the type is INT or UINT. */
450 int64_t m_int_value;
451 /** The value if the type is DOUBLE. */
453 };
454
455 /**
456 Element count for arrays and objects. Unused for other types.
457 */
459
460 /**
461 The full length (in bytes) of the binary representation of an array or
462 object, or the length of a string or opaque value. Unused for other types.
463 */
464 uint32_t m_length;
465
466 /**
467 The MySQL field type of the value, in case the type of the value is
468 OPAQUE. Otherwise, it is unused.
469 */
471
472 /** The JSON type of the value. */
474
475 /**
476 True if an array or an object uses the large storage format with 4
477 byte offsets instead of 2 byte offsets.
478 */
480
481 size_t key_entry_offset(size_t pos) const;
482 size_t value_entry_offset(size_t pos) const;
483 bool first_value_offset(size_t *offset) const;
484 bool element_offsets(size_t pos, size_t *start, size_t *end,
485 bool *inlined) const;
486};
487
488/**
489 Parse a JSON binary document.
490
491 @param[in] data a pointer to the binary data
492 @param[in] len the size of the binary document in bytes
493 @return an object that allows access to the contents of the document
494*/
496Value parse_binary(const char *data, size_t len);
497
498/**
499 How much space is needed for a JSON value when it is stored in the binary
500 format.
501
502 @param[in] thd THD handle
503 @param[in] value the JSON value to add to a document
504 @param[in] large true if the large storage format is used
505 @param[out] needed gets set to the amount of bytes needed to store
506 the value
507 @retval false if successful
508 @retval true if an error occurred while calculating the needed space
509*/
510#ifdef MYSQL_SERVER
511bool space_needed(const THD *thd, const Json_wrapper *value, bool large,
512 size_t *needed);
513#endif
514
515/**
516 Apply a function to every value in a JSON document. That is, apply
517 the function to the root node of the JSON document, to all its
518 children, grandchildren and so on.
519
520 @param value the root of the JSON document
521 @param func the function to apply
522 @retval true if the processing was stopped
523 @retval false if the processing was completed
524
525 @tparam Func a functor type that takes a #json_binary::Value
526 parameter and returns a `bool` which is `true` if the processing
527 should stop or `false` if the processing should continue with the
528 next node
529*/
530template <typename Func>
531bool for_each_node(const Value &value, const Func &func) {
532 if (func(value)) return true;
533
534 if (value.is_array() || value.is_object())
535 for (size_t i = 0, size = value.element_count(); i < size; ++i)
536 if (for_each_node(value.element(i), func)) return true;
537
538 return false;
539}
540} // namespace json_binary
541
542#endif /* JSON_BINARY_INCLUDED */
A field that stores a JSON value.
Definition: field.h:3976
JSON DOM abstract base class.
Definition: json_dom.h:173
Abstraction for accessing JSON values irrespective of whether they are (started out as) binary JSON v...
Definition: json_dom.h:1161
Using this class is fraught with peril, and you need to be very careful when doing so.
Definition: sql_string.h:168
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:34
Class used for reading JSON values that are stored in the binary format.
Definition: json_binary.h:198
double m_double_value
The value if the type is DOUBLE.
Definition: json_binary.h:452
EXPORT_JSON_FUNCTION Value key(size_t pos) const
Get the key of the member stored at the specified position in a JSON object.
Definition: json_binary.cc:1131
EXPORT_JSON_FUNCTION uint32_t element_count() const
Get the number of elements in an array, or the number of members in an object.
Definition: json_binary.h:275
EXPORT_JSON_FUNCTION const char * get_data() const
Get a pointer to the beginning of the STRING or OPAQUE data represented by this instance.
Definition: json_binary.h:234
EXPORT_JSON_FUNCTION Value(enum_field_types ft, const char *data, uint32_t len)
Constructor for values that represent opaque data.
Definition: json_binary.h:373
bool update_in_shadow(const Field_json *field, size_t pos, Json_wrapper *new_value, size_t data_offset, size_t data_length, const char *original, char *destination, bool *changed) const
Update a value in an array or object.
Definition: json_binary.cc:1727
EXPORT_JSON_FUNCTION Value lookup(const std::string &key) const
Definition: json_binary.h:300
bool first_value_offset(size_t *offset) const
Find the lowest possible offset where a value can be located inside this array or object.
Definition: json_binary.cc:1378
EXPORT_JSON_FUNCTION enum_field_types field_type() const
Get the MySQL field type of an opaque value.
Definition: json_binary.h:285
EXPORT_JSON_FUNCTION Value(enum_type t, const char *data, uint32_t bytes, uint32_t element_count, bool large)
Constructor for values that represent arrays or objects.
Definition: json_binary.h:361
EXPORT_JSON_FUNCTION size_t lookup_index(const char *key, size_t length) const
Get the index of the element with the specified key in a JSON object.
Definition: json_binary.cc:1183
EXPORT_JSON_FUNCTION int64_t get_int64() const
Get the value of an INT.
Definition: json_binary.h:251
bool m_large
True if an array or an object uses the large storage format with 4 byte offsets instead of 2 byte off...
Definition: json_binary.h:479
EXPORT_JSON_FUNCTION Value(const char *data, uint32_t len)
Constructor for values that represent strings.
Definition: json_binary.h:347
int64_t m_int_value
The value if the type is INT or UINT.
Definition: json_binary.h:450
bool remove_in_shadow(const Field_json *field, size_t pos, const char *original, char *destination) const
Remove a value from an array or object.
Definition: json_binary.cc:1914
EXPORT_JSON_FUNCTION Value element(size_t pos) const
Get the element at the specified position of a JSON array or a JSON object.
Definition: json_binary.cc:1093
bool raw_binary(const THD *thd, String *buf) const
Copy the binary representation of this value into a buffer, replacing the contents of the receiving b...
Definition: json_binary.cc:1256
EXPORT_JSON_FUNCTION uint32_t get_data_length() const
Get the length in bytes of the STRING or OPAQUE value represented by this instance.
Definition: json_binary.h:244
EXPORT_JSON_FUNCTION bool is_object() const
Is this value an object?
Definition: json_binary.h:386
EXPORT_JSON_FUNCTION size_t lookup_index(const std::string &key) const
Definition: json_binary.h:308
EXPORT_JSON_FUNCTION bool has_space(size_t pos, size_t needed, size_t *offset) const
Does this array or object have enough space to replace the value at the given position with another v...
Definition: json_binary.cc:1410
EXPORT_JSON_FUNCTION bool is_valid() const
Does this value, and all of its members, represent a valid JSON value?
Definition: json_binary.cc:867
EXPORT_JSON_FUNCTION Value(double val)
Constructor for values that represent doubles.
Definition: json_binary.h:343
uint32_t m_length
The full length (in bytes) of the binary representation of an array or object, or the length of a str...
Definition: json_binary.h:464
enum_type
Definition: json_binary.h:200
@ DOUBLE
Definition: json_binary.h:206
@ LITERAL_FALSE
Definition: json_binary.h:209
@ INT
Definition: json_binary.h:204
@ STRING
Definition: json_binary.h:203
@ OBJECT
Definition: json_binary.h:201
@ LITERAL_TRUE
Definition: json_binary.h:208
@ ERROR
Definition: json_binary.h:211
@ LITERAL_NULL
Definition: json_binary.h:207
@ UINT
Definition: json_binary.h:205
@ OPAQUE
Definition: json_binary.h:210
@ ARRAY
Definition: json_binary.h:202
size_t key_entry_offset(size_t pos) const
Get the offset of the key entry that describes the key of the member at a given position in this obje...
Definition: json_binary.cc:1511
EXPORT_JSON_FUNCTION Value()
Empty constructor.
Definition: json_binary.h:378
EXPORT_JSON_FUNCTION enum_type type() const
Definition: json_binary.h:223
EXPORT_JSON_FUNCTION bool to_std_string(std::string *buffer, const JsonDocumentDepthHandler &depth_handler) const
Format the JSON value to an external JSON string in buffer in the format of ISO/IEC 10646.
Definition: json_binary.cc:2104
EXPORT_JSON_FUNCTION Value(enum_type t)
Constructor for values that represent literals or errors.
Definition: json_binary.h:330
enum_field_types m_field_type
The MySQL field type of the value, in case the type of the value is OPAQUE.
Definition: json_binary.h:470
bool element_offsets(size_t pos, size_t *start, size_t *end, bool *inlined) const
Find the start offset and the end offset of the specified element.
Definition: json_binary.cc:1321
size_t value_entry_offset(size_t pos) const
Get the offset of the value entry that describes the element at a given position in this array or obj...
Definition: json_binary.cc:1524
EXPORT_JSON_FUNCTION bool to_pretty_std_string(std::string *buffer, const JsonDocumentDepthHandler &depth_handler) const
Format the JSON value to an external JSON string in buffer in the format of ISO/IEC 10646.
Definition: json_binary.cc:2116
EXPORT_JSON_FUNCTION bool is_array() const
Is this value an array?
Definition: json_binary.h:382
EXPORT_JSON_FUNCTION bool large_format() const
Does this value use the large storage format?
Definition: json_binary.h:227
bool get_free_space(const THD *thd, size_t *space) const
Get the amount of unused space in the binary representation of this value.
Definition: json_binary.cc:1967
enum_type m_type
The JSON type of the value.
Definition: json_binary.h:473
const char * m_data
Pointer to the start of the binary representation of the value.
Definition: json_binary.h:448
EXPORT_JSON_FUNCTION uint64_t get_uint64() const
Get the value of a UINT.
Definition: json_binary.h:258
int eq(const Value &val) const
Compare two Values.
Definition: json_binary.cc:2059
EXPORT_JSON_FUNCTION Value(enum_type t, int64_t val)
Constructor for values that represent ints or uints.
Definition: json_binary.h:337
EXPORT_JSON_FUNCTION bool is_backed_by(const String *str) const
Is this binary value pointing to data that is contained in the specified string.
Definition: json_binary.cc:1230
uint32_t m_element_count
Element count for arrays and objects.
Definition: json_binary.h:458
EXPORT_JSON_FUNCTION double get_double() const
Get the value of a DOUBLE.
Definition: json_binary.h:265
EXPORT_JSON_FUNCTION Value lookup(const char *key, size_t length) const
Get the value associated with the specified key in a JSON object.
Definition: json_binary.cc:1169
Fido Client Authentication nullptr
Definition: fido_client_plugin.cc:222
This file contains the field type.
enum_field_types
Column types for MySQL.
Definition: field_types.h:53
static void start(mysql_harness::PluginFuncEnv *env)
Definition: http_auth_backend_plugin.cc:177
#define EXPORT_JSON_FUNCTION
Definition: json_binary.h:170
std::function< void()> JsonDocumentDepthHandler
Definition: json_error_handler.h:32
uint32 element_count
Definition: my_tree.h:52
std::string str(const mysqlrouter::ConfigGenerator::Options::Endpoint &ep)
Definition: config_generator.cc:1044
Definition: buf0block_hint.cc:30
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
Definition: json_binary.cc:100
bool space_needed(const THD *thd, const Json_wrapper *value, bool large, size_t *needed)
How much space is needed for a JSON value when it is stored in the binary format.
Definition: json_binary.cc:1538
bool serialize(const THD *thd, const Json_dom *dom, String *dest)
Serialize the JSON document represented by dom to binary format in the destination string,...
Definition: json_binary.cc:132
bool for_each_node(const Value &value, const Func &func)
Apply a function to every value in a JSON document.
Definition: json_binary.h:531
Value parse_binary(const char *data, size_t len)
Parse a JSON binary document.
Definition: json_binary.cc:1068
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:420