Skip to content

Commit 52c51fe

Browse files
committed
Bug#25418534: JSON_EXTRACT USING WILDCARDS TAKES FOREVER
Patch #10: Split up seek_no_dup_elimination() in multiple helper functions (one per path leg type) to avoid having to go through the same switch statement over and over again when processing wildcards or ellipses. In json_binary::Value, make all the member variables non-const. This allows us to skip initialization of member variables that are not used. It also allows us to remove the custom assignment operator that works around the constness. Microbenchmarks (64-bit, Intel Core i7-4770 3.4 GHz, GCC 6.3): BM_JsonBinarySearchEllipsis 8902 ns/iter [+89.8%] BM_JsonBinarySearchEllipsis_OnlyOne 80 ns/iter [ -7.5%] BM_JsonBinarySearchKey 72 ns/iter [ -6.9%] Change-Id: I975da622899ff2eddc5505d9d9759996bf3d878e
1 parent 3b07831 commit 52c51fe

File tree

2 files changed

+279
-127
lines changed

2 files changed

+279
-127
lines changed

sql/json_binary.h

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@
134134
*/
135135

136136
#include <stddef.h>
137-
#include <new>
138137
#include <string>
139138

140139
#include "binary_log_types.h" // enum_field_types
@@ -317,17 +316,6 @@ class Value
317316
/** Empty constructor. Produces a value that represents an error condition. */
318317
Value() : Value(ERROR) {}
319318

320-
/** Assignment operator. */
321-
Value &operator=(const Value &from)
322-
{
323-
if (this != &from)
324-
{
325-
// Copy the entire from value into this.
326-
new (this) Value(from);
327-
}
328-
return *this;
329-
}
330-
331319
/** Is this value an array? */
332320
bool is_array() const { return m_type == ARRAY; }
333321

@@ -351,36 +339,36 @@ class Value
351339
*/
352340
const char *m_data;
353341
/** The value if the type is INT or UINT. */
354-
const int64 m_int_value;
342+
int64 m_int_value;
355343
/** The value if the type is DOUBLE. */
356-
const double m_double_value;
344+
double m_double_value;
357345
};
358346

359347
/**
360348
Element count for arrays and objects. Unused for other types.
361349
*/
362-
const uint32 m_element_count{};
350+
uint32 m_element_count;
363351

364352
/**
365353
The full length (in bytes) of the binary representation of an array or
366354
object, or the length of a string or opaque value. Unused for other types.
367355
*/
368-
const uint32 m_length{};
356+
uint32 m_length;
369357

370358
/**
371359
The MySQL field type of the value, in case the type of the value is
372360
OPAQUE. Otherwise, it is unused.
373361
*/
374-
const enum_field_types m_field_type{};
362+
enum_field_types m_field_type;
375363

376364
/** The JSON type of the value. */
377-
const enum_type m_type;
365+
enum_type m_type;
378366

379367
/**
380368
True if an array or an object uses the large storage format with 4
381369
byte offsets instead of 2 byte offsets.
382370
*/
383-
const bool m_large{};
371+
bool m_large;
384372

385373
size_t key_entry_offset(size_t pos) const;
386374
size_t value_entry_offset(size_t pos) const;
@@ -413,6 +401,35 @@ Value parse_binary(const char *data, size_t len);
413401
bool space_needed(const THD *thd, const Json_wrapper *value,
414402
bool large, size_t *needed);
415403

404+
/**
405+
Apply a function to every value in a JSON document. That is, apply
406+
the function to the root node of the JSON document, to all its
407+
children, grandchildren and so on.
408+
409+
@param value the root of the JSON document
410+
@param func the function to apply
411+
@retval true if the processing was stopped
412+
@retval false if the processing was completed
413+
414+
@tparam Func a functor type that takes a #json_binary::Value
415+
parameter and returns a `bool` which is `true` if the processing
416+
should stop or `false` if the processing should continue with the
417+
next node
418+
*/
419+
template <typename Func>
420+
bool for_each_node(const Value &value, const Func &func)
421+
{
422+
if (func(value))
423+
return true;
424+
425+
if (value.is_array() || value.is_object())
426+
for (size_t i= 0, size= value.element_count(); i < size; ++i)
427+
if (for_each_node(value.element(i), func))
428+
return true;
429+
430+
return false;
431+
}
432+
416433
}
417434

418435
#endif /* JSON_BINARY_INCLUDED */

0 commit comments

Comments
 (0)