30
30
#include < memory>
31
31
#include < string>
32
32
#include < utility>
33
+ #include < vector>
34
+
35
+ #ifdef MYSQL_SERVER
36
+ #include < sys/types.h>
37
+ #endif // MYSQL_SERVER
33
38
34
39
#include " my_byteorder.h"
35
- #include " my_sys.h"
40
+ #include " my_dbug.h"
41
+ #include " my_inttypes.h"
36
42
#include " mysql/strings/m_ctype.h"
37
- #include " mysqld_error.h"
38
- #ifdef MYSQL_SERVER
39
- #include " sql/check_stack.h"
40
- #endif
41
43
#include " sql-common/json_dom.h" // Json_dom
44
+ #include " sql-common/json_error_handler.h"
42
45
#include " sql-common/json_syntax_check.h"
43
- #include " sql/field.h" // Field_json
44
- #include " sql/sql_class.h" // THD
45
46
#include " sql/sql_const.h"
46
- #include " sql/system_variables.h"
47
- #include " sql/table.h" // TABLE::add_binary_diff()
48
47
#include " sql_string.h"
49
48
#include " template_utils.h" // down_cast
50
49
50
+ #ifdef MYSQL_SERVER
51
+ #include " my_sys.h"
52
+ #include " mysqld_error.h"
53
+ #include " sql/check_stack.h"
54
+ #include " sql/current_thd.h"
55
+ #include " sql/field.h"
56
+ #include " sql/table.h"
57
+ #endif // MYSQL_SERVER
58
+
51
59
namespace {
52
60
53
61
constexpr char JSONB_TYPE_SMALL_OBJECT = 0x0 ;
@@ -125,28 +133,36 @@ enum enum_serialization_result {
125
133
};
126
134
127
135
static enum_serialization_result serialize_json_value (
128
- const Json_dom *dom, size_t type_pos, String *dest, size_t depth ,
129
- bool small_parent, const JsonErrorHandler &json_depth_handler );
136
+ const Json_dom *dom, size_t type_pos, size_t depth, bool small_parent ,
137
+ const JsonSerializationErrorHandler &error_handler, String *dest );
130
138
static void write_offset_or_size (char *dest, size_t offset_or_size, bool large);
131
139
static uint8 offset_size (bool large);
132
140
133
- bool serialize (const Json_dom *dom, String *dest,
134
- const JsonErrorHandler &json_depth_handler,
135
- const JsonErrorHandler &json_key_handler,
136
- const JsonErrorHandler &json_value_handler) {
141
+ bool serialize (const Json_dom *dom,
142
+ const JsonSerializationErrorHandler &error_handler,
143
+ String *dest) {
137
144
// Reset the destination buffer.
138
145
dest->length (0 );
139
146
dest->set_charset (&my_charset_bin);
140
147
141
148
// Reserve space (one byte) for the type identifier.
142
149
if (dest->append (' \0 ' )) return true ; /* purecov: inspected */
143
- enum_serialization_result result =
144
- serialize_json_value (dom, 0 , dest, 0 , false , json_depth_handler);
145
150
146
- if (result == JSON_KEY_TOO_BIG) json_key_handler ();
147
- if (result == VALUE_TOO_BIG) json_value_handler ();
151
+ switch (serialize_json_value (dom, /* type_pos=*/ 0 , /* depth=*/ 0 ,
152
+ /* small_parent=*/ false , error_handler, dest)) {
153
+ case OK:
154
+ return false ;
155
+ case VALUE_TOO_BIG:
156
+ error_handler.ValueTooBig ();
157
+ return true ;
158
+ case JSON_KEY_TOO_BIG:
159
+ error_handler.KeyTooBig ();
160
+ return true ;
161
+ case FAILURE:
162
+ return true ;
163
+ }
148
164
149
- return result != OK;
165
+ return true ; /* purecov: deadcode */
150
166
}
151
167
152
168
/* *
@@ -496,16 +512,15 @@ static bool attempt_inline_value(const Json_dom *value, String *dest,
496
512
Serialize a JSON array at the end of the destination string.
497
513
498
514
@param array the JSON array to serialize
499
- @param dest the destination string
500
515
@param large if true, the large storage format will be used
501
516
@param depth the current nesting level
502
- @param json_depth_handler handler which will be called for JSON documents
503
- exceeding the maximum allowed depth
517
+ @param error_handler a handler that is invoked if an error occurs
518
+ @param dest the destination string
504
519
@return serialization status
505
520
*/
506
521
static enum_serialization_result serialize_json_array (
507
- const Json_array *array, String *dest, bool large, size_t depth,
508
- const JsonErrorHandler &json_depth_handler ) {
522
+ const Json_array *array, bool large, size_t depth,
523
+ const JsonSerializationErrorHandler &error_handler, String *dest ) {
509
524
#ifdef MYSQL_SERVER
510
525
if (check_stack_overrun (current_thd, STACK_MIN_SIZE, nullptr ))
511
526
return FAILURE; /* purecov: inspected */
@@ -514,7 +529,7 @@ static enum_serialization_result serialize_json_array(
514
529
const size_t start_pos = dest->length ();
515
530
const size_t size = array->size ();
516
531
517
- if (check_json_depth (++depth, json_depth_handler )) {
532
+ if (check_json_depth (++depth, error_handler )) {
518
533
return FAILURE;
519
534
}
520
535
@@ -542,8 +557,8 @@ static enum_serialization_result serialize_json_array(
542
557
size_t offset = dest->length () - start_pos;
543
558
if (is_too_big_for_json (offset, large)) return VALUE_TOO_BIG;
544
559
insert_offset_or_size (dest, entry_pos + 1 , offset, large);
545
- auto res = serialize_json_value (elt, entry_pos, dest, depth, !large,
546
- json_depth_handler );
560
+ auto res = serialize_json_value (elt, entry_pos, depth, !large,
561
+ error_handler, dest );
547
562
if (res != OK) return res;
548
563
}
549
564
entry_pos += entry_size;
@@ -562,16 +577,15 @@ static enum_serialization_result serialize_json_array(
562
577
Serialize a JSON object at the end of the destination string.
563
578
564
579
@param object the JSON object to serialize
565
- @param dest the destination string
566
580
@param large if true, the large storage format will be used
567
581
@param depth the current nesting level
568
- @param json_depth_handler handler which will be called for JSON documents
569
- exceeding the maximum allowed depth
582
+ @param error_handler a handler that is invoked if an error occurs
583
+ @param dest the destination string
570
584
@return serialization status
571
585
*/
572
586
static enum_serialization_result serialize_json_object (
573
- const Json_object *object, String *dest, bool large, size_t depth,
574
- const JsonErrorHandler &json_depth_handler ) {
587
+ const Json_object *object, bool large, size_t depth,
588
+ const JsonSerializationErrorHandler &error_handler, String *dest ) {
575
589
#ifdef MYSQL_SERVER
576
590
if (check_stack_overrun (current_thd, STACK_MIN_SIZE, nullptr ))
577
591
return FAILURE; /* purecov: inspected */
@@ -580,7 +594,7 @@ static enum_serialization_result serialize_json_object(
580
594
const size_t start_pos = dest->length ();
581
595
const size_t size = object->cardinality ();
582
596
583
- if (check_json_depth (++depth, json_depth_handler )) {
597
+ if (check_json_depth (++depth, error_handler )) {
584
598
return FAILURE;
585
599
}
586
600
@@ -630,8 +644,8 @@ static enum_serialization_result serialize_json_object(
630
644
size_t offset = dest->length () - start_pos;
631
645
if (is_too_big_for_json (offset, large)) return VALUE_TOO_BIG;
632
646
insert_offset_or_size (dest, entry_pos + 1 , offset, large);
633
- res = serialize_json_value (child, entry_pos, dest, depth, !large,
634
- json_depth_handler );
647
+ res = serialize_json_value (child, entry_pos, depth, !large, error_handler ,
648
+ dest );
635
649
if (res != OK) return res;
636
650
}
637
651
entry_pos += value_entry_size;
@@ -714,14 +728,13 @@ static enum_serialization_result serialize_datetime(const Json_datetime *jdt,
714
728
@param depth the current nesting level
715
729
@param small_parent tells if @a dom is contained in an array or object
716
730
which is stored in the small storage format
717
- @param json_depth_handler handler which will be called for JSON documents
718
- exceeding the maximum allowed depth
731
+ @param error_handler a handler that is invoked if an error occurs
719
732
720
733
@return serialization status
721
734
*/
722
735
static enum_serialization_result serialize_json_value (
723
- const Json_dom *dom, size_t type_pos, String *dest, size_t depth ,
724
- bool small_parent, const JsonErrorHandler &json_depth_handler ) {
736
+ const Json_dom *dom, size_t type_pos, size_t depth, bool small_parent ,
737
+ const JsonSerializationErrorHandler &error_handler, String *dest ) {
725
738
const size_t start_pos = dest->length ();
726
739
assert (type_pos < start_pos);
727
740
@@ -731,8 +744,8 @@ static enum_serialization_result serialize_json_value(
731
744
case enum_json_type::J_ARRAY: {
732
745
const Json_array *array = down_cast<const Json_array *>(dom);
733
746
(*dest)[type_pos] = JSONB_TYPE_SMALL_ARRAY;
734
- result =
735
- serialize_json_array (array, dest, false , depth, json_depth_handler );
747
+ result = serialize_json_array (array, /* large= */ false , depth,
748
+ error_handler, dest );
736
749
/*
737
750
If the array was too large to fit in the small storage format,
738
751
reset the destination buffer and retry with the large storage
@@ -747,16 +760,16 @@ static enum_serialization_result serialize_json_value(
747
760
if (small_parent) return VALUE_TOO_BIG;
748
761
dest->length (start_pos);
749
762
(*dest)[type_pos] = JSONB_TYPE_LARGE_ARRAY;
750
- result =
751
- serialize_json_array (array, dest, true , depth, json_depth_handler );
763
+ result = serialize_json_array (array, /* large= */ true , depth,
764
+ error_handler, dest );
752
765
}
753
766
break ;
754
767
}
755
768
case enum_json_type::J_OBJECT: {
756
769
const Json_object *object = down_cast<const Json_object *>(dom);
757
770
(*dest)[type_pos] = JSONB_TYPE_SMALL_OBJECT;
758
- result =
759
- serialize_json_object (object, dest, false , depth, json_depth_handler );
771
+ result = serialize_json_object (object, /* large= */ false , depth,
772
+ error_handler, dest );
760
773
/*
761
774
If the object was too large to fit in the small storage format,
762
775
reset the destination buffer and retry with the large storage
@@ -771,8 +784,8 @@ static enum_serialization_result serialize_json_value(
771
784
if (small_parent) return VALUE_TOO_BIG;
772
785
dest->length (start_pos);
773
786
(*dest)[type_pos] = JSONB_TYPE_LARGE_OBJECT;
774
- result = serialize_json_object (object, dest, true , depth,
775
- json_depth_handler );
787
+ result = serialize_json_object (object, /* large= */ true , depth,
788
+ error_handler, dest );
776
789
}
777
790
break ;
778
791
}
@@ -1262,18 +1275,12 @@ bool Value::is_backed_by(const String *str) const {
1262
1275
Copy the binary representation of this value into a buffer,
1263
1276
replacing the contents of the receiving buffer.
1264
1277
1278
+ @param error_handler a handler that is invoked if an error occurs
1265
1279
@param buf the receiving buffer
1266
- @param json_depth_handler handler which will be called for JSON documents
1267
- exceeding the maximum allowed depth
1268
- @param json_key_handler handler which will be called for JSON documents
1269
- having keys too large
1270
- @param json_value_handler handler which will be called for JSON documents
1271
- having values too large
1272
1280
@return false on success, true otherwise
1273
1281
*/
1274
- bool Value::raw_binary (String *buf, const JsonErrorHandler &json_depth_handler,
1275
- const JsonErrorHandler &json_key_handler,
1276
- const JsonErrorHandler &json_value_handler) const {
1282
+ bool Value::raw_binary (const JsonSerializationErrorHandler &error_handler,
1283
+ String *buf) const {
1277
1284
// It's not safe to overwrite ourselves.
1278
1285
assert (!is_backed_by (buf));
1279
1286
@@ -1296,29 +1303,24 @@ bool Value::raw_binary(String *buf, const JsonErrorHandler &json_depth_handler,
1296
1303
buf->append (m_data, m_length);
1297
1304
case INT: {
1298
1305
Json_int i (get_int64 ());
1299
- return serialize (&i, buf, json_depth_handler, json_key_handler,
1300
- json_value_handler);
1306
+ return serialize (&i, error_handler, buf);
1301
1307
}
1302
1308
case UINT: {
1303
1309
Json_uint i (get_uint64 ());
1304
- return serialize (&i, buf, json_depth_handler, json_key_handler,
1305
- json_value_handler);
1310
+ return serialize (&i, error_handler, buf);
1306
1311
}
1307
1312
case DOUBLE: {
1308
1313
Json_double d (get_double ());
1309
- return serialize (&d, buf, json_depth_handler, json_key_handler,
1310
- json_value_handler);
1314
+ return serialize (&d, error_handler, buf);
1311
1315
}
1312
1316
case LITERAL_NULL: {
1313
1317
Json_null n;
1314
- return serialize (&n, buf, json_depth_handler, json_key_handler,
1315
- json_value_handler);
1318
+ return serialize (&n, error_handler, buf);
1316
1319
}
1317
1320
case LITERAL_TRUE:
1318
1321
case LITERAL_FALSE: {
1319
1322
Json_boolean b (m_type == LITERAL_TRUE);
1320
- return serialize (&b, buf, json_depth_handler, json_key_handler,
1321
- json_value_handler);
1323
+ return serialize (&b, error_handler, buf);
1322
1324
}
1323
1325
case OPAQUE:
1324
1326
return buf->append (JSONB_TYPE_OPAQUE) || buf->append (field_type ()) ||
@@ -1567,8 +1569,7 @@ bool space_needed(const Json_wrapper *value, bool large, size_t *needed) {
1567
1569
1568
1570
// Serialize the value to a temporary buffer to find out how big it is.
1569
1571
StringBuffer<STRING_BUFFER_USUAL_SIZE> buf;
1570
- if (value->to_binary (&buf, JsonDepthErrorHandler, JsonKeyTooBigErrorHandler,
1571
- JsonValueTooBigErrorHandler, InvalidJsonErrorHandler))
1572
+ if (value->to_binary (JsonSerializationDefaultErrorHandler (), &buf))
1572
1573
return true ; /* purecov: inspected */
1573
1574
1574
1575
assert (buf.length () > 1 );
@@ -1780,9 +1781,7 @@ bool Value::update_in_shadow(const Field_json *field, size_t pos,
1780
1781
char *value_dest = destination + value_offset;
1781
1782
1782
1783
StringBuffer<STRING_BUFFER_USUAL_SIZE> buffer;
1783
- if (new_value->to_binary (
1784
- &buffer, JsonDepthErrorHandler, JsonKeyTooBigErrorHandler,
1785
- JsonValueTooBigErrorHandler, InvalidJsonErrorHandler))
1784
+ if (new_value->to_binary (JsonSerializationDefaultErrorHandler (), &buffer))
1786
1785
return true ; /* purecov: inspected */
1787
1786
1788
1787
assert (buffer.length () > 1 );
0 commit comments