Skip to content

Commit b175763

Browse files
Sergei Krivonosohhmm
authored andcommitted
MDEV-23766: add Json_writer consistency asserts to check array/object sequence
1 parent cf047ef commit b175763

File tree

2 files changed

+116
-42
lines changed

2 files changed

+116
-42
lines changed

sql/my_json_writer.cc

Lines changed: 96 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818
#include "sql_string.h"
1919
#include "my_json_writer.h"
2020

21+
#ifndef NDEBUG
22+
bool Json_writer::named_item_expected() const
23+
{
24+
return named_items_expectation.size()
25+
&& named_items_expectation.back();
26+
}
27+
#endif
28+
2129
void Json_writer::append_indent()
2230
{
2331
if (!document_start)
@@ -26,9 +34,27 @@ void Json_writer::append_indent()
2634
output.append(' ');
2735
}
2836

29-
void Json_writer::start_object()
37+
inline void Json_writer::on_start_object()
3038
{
39+
#ifndef NDEBUG
40+
if(!is_on_fmt_helper_call)
41+
{
42+
DBUG_ASSERT(got_name == named_item_expected());
43+
named_items_expectation.push_back(true);
44+
}
45+
46+
bool was_on_fmt_helper_call= is_on_fmt_helper_call;
47+
is_on_fmt_helper_call= true;
48+
#endif
3149
fmt_helper.on_start_object();
50+
#ifndef NDEBUG
51+
is_on_fmt_helper_call= was_on_fmt_helper_call;
52+
#endif
53+
}
54+
55+
void Json_writer::start_object()
56+
{
57+
on_start_object();
3258

3359
if (!element_started)
3460
start_element();
@@ -38,11 +64,36 @@ void Json_writer::start_object()
3864
first_child=true;
3965
element_started= false;
4066
document_start= false;
67+
#ifndef NDEBUG
68+
got_name= false;
69+
#endif
70+
}
71+
72+
bool Json_writer::on_start_array()
73+
{
74+
#ifndef NDEBUG
75+
bool was_on_fmt_helper_call= is_on_fmt_helper_call;
76+
is_on_fmt_helper_call= true;
77+
#endif
78+
bool helped= fmt_helper.on_start_array();
79+
#ifndef NDEBUG
80+
is_on_fmt_helper_call= was_on_fmt_helper_call;
81+
#endif
82+
return helped;
4183
}
4284

4385
void Json_writer::start_array()
4486
{
45-
if (fmt_helper.on_start_array())
87+
#ifndef NDEBUG
88+
if(!is_on_fmt_helper_call)
89+
{
90+
DBUG_ASSERT(got_name == named_item_expected());
91+
named_items_expectation.push_back(false);
92+
got_name= false;
93+
}
94+
#endif
95+
96+
if (on_start_array())
4697
return;
4798

4899
if (!element_started)
@@ -58,6 +109,11 @@ void Json_writer::start_array()
58109

59110
void Json_writer::end_object()
60111
{
112+
#ifndef NDEBUG
113+
named_items_expectation.pop_back();
114+
DBUG_ASSERT(!got_name);
115+
got_name= false;
116+
#endif
61117
indent_level-=INDENT_SIZE;
62118
if (!first_child)
63119
append_indent();
@@ -68,6 +124,10 @@ void Json_writer::end_object()
68124

69125
void Json_writer::end_array()
70126
{
127+
#ifndef NDEBUG
128+
named_items_expectation.pop_back();
129+
got_name= false;
130+
#endif
71131
if (fmt_helper.on_end_array())
72132
return;
73133
indent_level-=INDENT_SIZE;
@@ -80,31 +140,25 @@ void Json_writer::end_array()
80140
Json_writer& Json_writer::add_member(const char *name)
81141
{
82142
size_t len= strlen(name);
83-
if (fmt_helper.on_add_member(name, len))
84-
return *this; // handled
85-
86-
// assert that we are in an object
87-
DBUG_ASSERT(!element_started);
88-
start_element();
89-
90-
output.append('"');
91-
output.append(name, len);
92-
output.append("\": ", 3);
93-
return *this;
143+
return add_member(name, len);
94144
}
95145

96146
Json_writer& Json_writer::add_member(const char *name, size_t len)
97147
{
98-
if (fmt_helper.on_add_member(name, len))
99-
return *this; // handled
100-
101-
// assert that we are in an object
102-
DBUG_ASSERT(!element_started);
103-
start_element();
148+
if (!fmt_helper.on_add_member(name, len))
149+
{
150+
// assert that we are in an object
151+
DBUG_ASSERT(!element_started);
152+
start_element();
104153

105-
output.append('"');
106-
output.append(name, len);
107-
output.append("\": ");
154+
output.append('"');
155+
output.append(name, len);
156+
output.append("\": ", 3);
157+
}
158+
#ifndef NDEBUG
159+
if (!is_on_fmt_helper_call)
160+
got_name= true;
161+
#endif
108162
return *this;
109163
}
110164

@@ -200,19 +254,13 @@ void Json_writer::add_null()
200254
void Json_writer::add_unquoted_str(const char* str)
201255
{
202256
size_t len= strlen(str);
203-
if (fmt_helper.on_add_str(str, len))
204-
return;
205-
206-
if (!element_started)
207-
start_element();
208-
209-
output.append(str, len);
210-
element_started= false;
257+
add_unquoted_str(str, len);
211258
}
212259

213260
void Json_writer::add_unquoted_str(const char* str, size_t len)
214261
{
215-
if (fmt_helper.on_add_str(str, len))
262+
DBUG_ASSERT(is_on_fmt_helper_call || got_name == named_item_expected());
263+
if (on_add_str(str, len))
216264
return;
217265

218266
if (!element_started)
@@ -222,19 +270,24 @@ void Json_writer::add_unquoted_str(const char* str, size_t len)
222270
element_started= false;
223271
}
224272

273+
inline bool Json_writer::on_add_str(const char *str, size_t num_bytes)
274+
{
275+
#ifndef NDEBUG
276+
got_name= false;
277+
bool was_on_fmt_helper_call= is_on_fmt_helper_call;
278+
is_on_fmt_helper_call= true;
279+
#endif
280+
bool helped= fmt_helper.on_add_str(str, num_bytes);
281+
#ifndef NDEBUG
282+
is_on_fmt_helper_call= was_on_fmt_helper_call;
283+
#endif
284+
return helped;
285+
}
286+
225287
void Json_writer::add_str(const char *str)
226288
{
227289
size_t len= strlen(str);
228-
if (fmt_helper.on_add_str(str, len))
229-
return;
230-
231-
if (!element_started)
232-
start_element();
233-
234-
output.append('"');
235-
output.append(str, len);
236-
output.append('"');
237-
element_started= false;
290+
add_str(str, len);
238291
}
239292

240293
/*
@@ -243,7 +296,8 @@ void Json_writer::add_str(const char *str)
243296

244297
void Json_writer::add_str(const char* str, size_t num_bytes)
245298
{
246-
if (fmt_helper.on_add_str(str, num_bytes))
299+
DBUG_ASSERT(is_on_fmt_helper_call || got_name == named_item_expected());
300+
if (on_add_str(str, num_bytes))
247301
return;
248302

249303
if (!element_started)

sql/my_json_writer.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,17 @@ class String_with_limit
181181

182182
class Json_writer
183183
{
184+
#ifndef NDEBUG
185+
186+
std::vector<bool> named_items_expectation;
187+
188+
bool named_item_expected() const;
189+
190+
bool got_name;
191+
bool is_on_fmt_helper_call;
192+
193+
#endif
194+
184195
public:
185196
/* Add a member. We must be in an object. */
186197
Json_writer& add_member(const char *name);
@@ -204,6 +215,11 @@ class Json_writer
204215
private:
205216
void add_unquoted_str(const char* val);
206217
void add_unquoted_str(const char* val, size_t len);
218+
219+
bool on_add_str(const char *str, size_t num_bytes);
220+
bool on_start_array();
221+
void on_start_object();
222+
207223
public:
208224
/* Start a child object */
209225
void start_object();
@@ -221,6 +237,10 @@ class Json_writer
221237
size_t get_truncated_bytes() { return output.get_truncated_bytes(); }
222238

223239
Json_writer() :
240+
#ifndef NDEBUG
241+
got_name(false),
242+
is_on_fmt_helper_call(false),
243+
#endif
224244
indent_level(0), document_start(true), element_started(false),
225245
first_child(true)
226246
{

0 commit comments

Comments
 (0)