Skip to content

Commit 59d7202

Browse files
committed
Bug#35640263: Refactoring of json_diff/json_binary to enable HW
support for partial json [4/6, serialize, noclose] Some error checking and error reporting in the json_binary::serialize* functions is wrapped in "#ifdef MYSQL_SERVER" so that it is not invoked when called from client code. This does however not allow them to be called from plugin code running in the server without a THD. This patch moves the remaining error checking and reporting into the error handler, so that the functions can also be called from server-side code that doesn't have a THD, if an appropriate error handler object is provided. Specifically, the code for checking and reporting stack overrun and internal errors is stubbed out. Change-Id: Ic4841121e313a1c763658388e2ef1ad4e0c6871e
1 parent aa9e300 commit 59d7202

12 files changed

+125
-82
lines changed

client/json_client_library_main.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ class CoutSerializationErrorHandler : public JsonSerializationErrorHandler {
5353
void ValueTooBig() const override { std::cout << "Value too big"; }
5454
void TooDeep() const override { CoutDefaultDepthHandler(); }
5555
void InvalidJson() const override { std::cout << "Invalid JSON"; }
56+
void InternalError(const char *message) const override {
57+
std::cout << "Internal error: " << message;
58+
}
59+
bool CheckStack() const override {
60+
std::cout << "Checking stack\n";
61+
return false;
62+
}
5663
};
5764

5865
} // namespace

sql-common/json_binary.cc

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -521,10 +521,9 @@ static bool attempt_inline_value(const Json_dom *value, String *dest,
521521
static enum_serialization_result serialize_json_array(
522522
const Json_array *array, bool large, size_t depth,
523523
const JsonSerializationErrorHandler &error_handler, String *dest) {
524-
#ifdef MYSQL_SERVER
525-
if (check_stack_overrun(current_thd, STACK_MIN_SIZE, nullptr))
524+
if (error_handler.CheckStack()) {
526525
return FAILURE; /* purecov: inspected */
527-
#endif // ifdef MYSQL_SERVER
526+
}
528527

529528
const size_t start_pos = dest->length();
530529
const size_t size = array->size();
@@ -586,10 +585,9 @@ static enum_serialization_result serialize_json_array(
586585
static enum_serialization_result serialize_json_object(
587586
const Json_object *object, bool large, size_t depth,
588587
const JsonSerializationErrorHandler &error_handler, String *dest) {
589-
#ifdef MYSQL_SERVER
590-
if (check_stack_overrun(current_thd, STACK_MIN_SIZE, nullptr))
588+
if (error_handler.CheckStack()) {
591589
return FAILURE; /* purecov: inspected */
592-
#endif // ifdef MYSQL_SERVER
590+
}
593591

594592
const size_t start_pos = dest->length();
595593
const size_t size = object->cardinality();
@@ -878,9 +876,7 @@ static enum_serialization_result serialize_json_value(
878876
case enum_json_type::J_ERROR:
879877
/* purecov: begin deadcode */
880878
assert(false);
881-
#ifdef MYSQL_SERVER
882-
my_error(ER_INTERNAL_ERROR, MYF(0), "JSON serialization failed");
883-
#endif
879+
error_handler.InternalError("JSON serialization failed");
884880
return FAILURE;
885881
/* purecov: end */
886882
}
@@ -1569,8 +1565,10 @@ bool space_needed(const Json_wrapper *value, bool large, size_t *needed) {
15691565

15701566
// Serialize the value to a temporary buffer to find out how big it is.
15711567
StringBuffer<STRING_BUFFER_USUAL_SIZE> buf;
1572-
if (value->to_binary(JsonSerializationDefaultErrorHandler(), &buf))
1568+
if (value->to_binary(JsonSerializationDefaultErrorHandler(current_thd),
1569+
&buf)) {
15731570
return true; /* purecov: inspected */
1571+
}
15741572

15751573
assert(buf.length() > 1);
15761574

@@ -1781,8 +1779,10 @@ bool Value::update_in_shadow(const Field_json *field, size_t pos,
17811779
char *value_dest = destination + value_offset;
17821780

17831781
StringBuffer<STRING_BUFFER_USUAL_SIZE> buffer;
1784-
if (new_value->to_binary(JsonSerializationDefaultErrorHandler(), &buffer))
1782+
if (new_value->to_binary(JsonSerializationDefaultErrorHandler(current_thd),
1783+
&buffer)) {
17851784
return true; /* purecov: inspected */
1785+
}
17861786

17871787
assert(buffer.length() > 1);
17881788

sql-common/json_diff.cc

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,12 @@ size_t Json_diff::binary_length() const {
151151
if (operation() != enum_json_diff_operation::REMOVE) {
152152
// value
153153
buf.length(0);
154-
if (value().to_binary(JsonSerializationDefaultErrorHandler(), &buf))
154+
const THD *const thd = current_thd;
155+
if (value().to_binary(JsonSerializationDefaultErrorHandler(thd), &buf))
155156
assert(0); /* purecov: deadcode */
156-
if (buf.length() > current_thd->variables.max_allowed_packet) {
157+
if (buf.length() > thd->variables.max_allowed_packet) {
157158
my_error(ER_WARN_ALLOWED_PACKET_OVERFLOWED, MYF(0),
158-
"json_binary::serialize",
159-
current_thd->variables.max_allowed_packet);
159+
"json_binary::serialize", thd->variables.max_allowed_packet);
160160
assert(0);
161161
}
162162
ret += length_of_length_and_string(buf.length());
@@ -237,13 +237,14 @@ bool Json_diff::write_binary(String *to) const {
237237
DBUG_SET("+d,binlog_corrupt_write_length_and_string_bad_char");
238238
});
239239
#endif // ifndef NDEBUG
240-
if (value().to_binary(JsonSerializationDefaultErrorHandler(), &buf) ||
241-
write_length_and_string(to, buf))
240+
const THD *const thd = current_thd;
241+
if (value().to_binary(JsonSerializationDefaultErrorHandler(thd), &buf) ||
242+
write_length_and_string(to, buf)) {
242243
return true; /* purecov: inspected */ // OOM, error is reported
243-
if (buf.length() > current_thd->variables.max_allowed_packet) {
244+
}
245+
if (buf.length() > thd->variables.max_allowed_packet) {
244246
my_error(ER_WARN_ALLOWED_PACKET_OVERFLOWED, MYF(0),
245-
"json_binary::serialize",
246-
current_thd->variables.max_allowed_packet);
247+
"json_binary::serialize", thd->variables.max_allowed_packet);
247248
return true;
248249
}
249250
DBUG_PRINT("info",

sql-common/json_dom.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3565,7 +3565,8 @@ bool Json_wrapper::attempt_binary_update(const Field_json *field,
35653565
*/
35663566
const char *original;
35673567
if (result->is_empty()) {
3568-
if (m_value.raw_binary(JsonSerializationDefaultErrorHandler(), result))
3568+
if (m_value.raw_binary(JsonSerializationDefaultErrorHandler(current_thd),
3569+
result))
35693570
return true; /* purecov: inspected */
35703571
original = field->get_binary();
35713572
} else {
@@ -3643,7 +3644,8 @@ bool Json_wrapper::binary_remove(const Field_json *field,
36433644
*/
36443645
const char *original;
36453646
if (result->is_empty()) {
3646-
if (m_value.raw_binary(JsonSerializationDefaultErrorHandler(), result)) {
3647+
if (m_value.raw_binary(JsonSerializationDefaultErrorHandler(current_thd),
3648+
result)) {
36473649
return true; /* purecov: inspected */
36483650
}
36493651
original = field->get_binary();

sql-common/json_error_handler.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "my_inttypes.h"
2626
#include "my_sys.h"
2727
#include "mysqld_error.h"
28+
#include "sql/check_stack.h"
29+
#include "sql/sql_const.h"
2830

2931
void JsonParseDefaultErrorHandler::operator()(const char *parse_err,
3032
size_t err_offset) const {
@@ -49,3 +51,12 @@ void JsonSerializationDefaultErrorHandler::TooDeep() const {
4951
void JsonSerializationDefaultErrorHandler::InvalidJson() const {
5052
my_error(ER_INVALID_JSON_BINARY_DATA, MYF(0));
5153
}
54+
55+
void JsonSerializationDefaultErrorHandler::InternalError(
56+
const char *message) const {
57+
my_error(ER_INTERNAL_ERROR, MYF(0), message);
58+
}
59+
60+
bool JsonSerializationDefaultErrorHandler::CheckStack() const {
61+
return check_stack_overrun(m_thd, STACK_MIN_SIZE, nullptr);
62+
}

sql-common/json_error_handler.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include <cstdlib>
2727
#include <functional>
2828

29+
class THD;
30+
2931
using JsonParseErrorHandler =
3032
std::function<void(const char *parse_err, size_t err_offset)>;
3133
using JsonErrorHandler = std::function<void()>;
@@ -55,6 +57,13 @@ class JsonSerializationErrorHandler {
5557

5658
/// Called when an invalid JSON value is encountered.
5759
virtual void InvalidJson() const = 0;
60+
61+
/// Called when an internal error occurs.
62+
virtual void InternalError(const char *message) const = 0;
63+
64+
/// Check if the stack is about to be exhausted, and report the error.
65+
/// @return true if the stack is about to be exhausted, false otherwise.
66+
virtual bool CheckStack() const = 0;
5867
};
5968

6069
#ifdef MYSQL_SERVER
@@ -80,10 +89,16 @@ void JsonDepthErrorHandler();
8089
class JsonSerializationDefaultErrorHandler final
8190
: public JsonSerializationErrorHandler {
8291
public:
92+
explicit JsonSerializationDefaultErrorHandler(const THD *thd) : m_thd(thd) {}
8393
void KeyTooBig() const override;
8494
void ValueTooBig() const override;
8595
void TooDeep() const override;
8696
void InvalidJson() const override;
97+
void InternalError(const char *message) const override;
98+
bool CheckStack() const override;
99+
100+
private:
101+
const THD *m_thd;
87102
};
88103

89104
#endif // MYSQL_SERVER

sql/field.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7699,15 +7699,15 @@ type_conversion_status Field_json::store(const char *from, size_t length,
76997699

77007700
if (dom.get() == nullptr) return TYPE_ERR_BAD_VALUE;
77017701

7702-
if (json_binary::serialize(dom.get(), JsonSerializationDefaultErrorHandler(),
7703-
&value)) {
7702+
const THD *const thd = current_thd;
7703+
if (json_binary::serialize(
7704+
dom.get(), JsonSerializationDefaultErrorHandler(thd), &value)) {
77047705
return TYPE_ERR_BAD_VALUE;
77057706
}
77067707

7707-
if (value.length() > current_thd->variables.max_allowed_packet) {
7708+
if (value.length() > thd->variables.max_allowed_packet) {
77087709
my_error(ER_WARN_ALLOWED_PACKET_OVERFLOWED, MYF(0),
7709-
"json_binary::serialize",
7710-
current_thd->variables.max_allowed_packet);
7710+
"json_binary::serialize", thd->variables.max_allowed_packet);
77117711
return TYPE_ERR_BAD_VALUE;
77127712
}
77137713

@@ -7802,13 +7802,13 @@ type_conversion_status Field_json::store_json(const Json_wrapper *json) {
78027802
StringBuffer<STRING_BUFFER_USUAL_SIZE> tmpstr;
78037803
String *buffer = json->is_binary_backed_by(&value) ? &tmpstr : &value;
78047804

7805-
if (json->to_binary(JsonSerializationDefaultErrorHandler(), buffer))
7805+
const THD *const thd = current_thd;
7806+
if (json->to_binary(JsonSerializationDefaultErrorHandler(thd), buffer))
78067807
return TYPE_ERR_BAD_VALUE;
78077808

7808-
if (buffer->length() > current_thd->variables.max_allowed_packet) {
7809+
if (buffer->length() > thd->variables.max_allowed_packet) {
78097810
my_error(ER_WARN_ALLOWED_PACKET_OVERFLOWED, MYF(0),
7810-
"json_binary::serialize",
7811-
current_thd->variables.max_allowed_packet);
7811+
"json_binary::serialize", thd->variables.max_allowed_packet);
78127812
return TYPE_ERR_BAD_VALUE;
78137813
}
78147814

sql/item_json_func.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3572,13 +3572,13 @@ longlong Item_func_json_storage_size::val_int() {
35723572
null_value = args[0]->null_value;
35733573
if (null_value) return 0;
35743574

3575-
if (wrapper.to_binary(JsonSerializationDefaultErrorHandler(), &buffer))
3575+
const THD *const thd = current_thd;
3576+
if (wrapper.to_binary(JsonSerializationDefaultErrorHandler(thd), &buffer))
35763577
return error_int(); /* purecov: inspected */
35773578

3578-
if (buffer.length() > current_thd->variables.max_allowed_packet) {
3579+
if (buffer.length() > thd->variables.max_allowed_packet) {
35793580
my_error(ER_WARN_ALLOWED_PACKET_OVERFLOWED, MYF(0),
3580-
"json_binary::serialize",
3581-
current_thd->variables.max_allowed_packet);
3581+
"json_binary::serialize", thd->variables.max_allowed_packet);
35823582
return error_int();
35833583
}
35843584
return buffer.length();

sql/rpl_async_conn_failover_configuration_propagation.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ bool Rpl_acf_configuration_handler::send_managed_data(
596596
return true;
597597
}
598598

599+
const THD *const thd = current_thd;
599600
for (auto managed_detail : managed_list) {
600601
auto managed = configuration.add_managed();
601602
managed->set_channel(std::get<0>(managed_detail));
@@ -605,13 +606,12 @@ bool Rpl_acf_configuration_handler::send_managed_data(
605606
// Convert Json_wrapper to binary format
606607
String buffer;
607608
if (std::get<3>(managed_detail)
608-
.to_binary(JsonSerializationDefaultErrorHandler(), &buffer)) {
609+
.to_binary(JsonSerializationDefaultErrorHandler(thd), &buffer)) {
609610
return true;
610611
}
611-
if (buffer.length() > current_thd->variables.max_allowed_packet) {
612+
if (buffer.length() > thd->variables.max_allowed_packet) {
612613
my_error(ER_WARN_ALLOWED_PACKET_OVERFLOWED, MYF(0),
613-
"json_binary::serialize",
614-
current_thd->variables.max_allowed_packet);
614+
"json_binary::serialize", thd->variables.max_allowed_packet);
615615
return true;
616616
}
617617

@@ -750,6 +750,7 @@ bool Rpl_acf_configuration_handler::get_configuration(
750750
return error;
751751
}
752752

753+
const THD *const thd = current_thd;
753754
configuration.set_managed_version(table_managed.get_version());
754755
for (RPL_FAILOVER_MANAGED_JSON_TUPLE managed_tuple : managed_list) {
755756
protobuf_replication_asynchronous_connection_failover::Managed *managed =
@@ -761,13 +762,12 @@ bool Rpl_acf_configuration_handler::get_configuration(
761762
// Convert Json_wrapper to binary format
762763
String buffer;
763764
if (std::get<3>(managed_tuple)
764-
.to_binary(JsonSerializationDefaultErrorHandler(), &buffer)) {
765+
.to_binary(JsonSerializationDefaultErrorHandler(thd), &buffer)) {
765766
return true;
766767
}
767-
if (buffer.length() > current_thd->variables.max_allowed_packet) {
768+
if (buffer.length() > thd->variables.max_allowed_packet) {
768769
my_error(ER_WARN_ALLOWED_PACKET_OVERFLOWED, MYF(0),
769-
"json_binary::serialize",
770-
current_thd->variables.max_allowed_packet);
770+
"json_binary::serialize", thd->variables.max_allowed_packet);
771771
return true;
772772
}
773773

0 commit comments

Comments
 (0)