diff --git a/include/json_lib.h b/include/json_lib.h index 4abb4dac239..2248b1a9388 100644 --- a/include/json_lib.h +++ b/include/json_lib.h @@ -283,13 +283,13 @@ int json_key_matches(json_engine_t *je, json_string_t *k); int json_read_value(json_engine_t *j); /* - * smart_read_value() reads parses a scalar value and value length from the json engine, + * json_smart_read_value() reads parses a scalar value and value length from the json engine, * and copies them into `value` and `value_length` respectively. * It should only be called when the json_engine state is JST_VALUE. * If it encounters a non-scalar value (say object or array) before getting to value_len, * such value is also read and copied into value. */ -enum json_types smart_read_value(json_engine_t *je, const char **value, int *value_len); +enum json_types json_smart_read_value(json_engine_t *je, const char **value, int *value_len); /* json_skip_key() makes parser skip the content of the current diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 3ab23e6ff1d..684e0a57da3 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -61,8 +61,21 @@ the collected statistics in the persistent statistical tables only when the value of the variable 'use_stat_tables' is not equal to "never". -*/ - +*/ + +/* + * json_get_array_items expects a JSON array as argument, + * and pushes the elements of the array into the `container` vector. + * It only works if all the elements in the original JSON array + * are scalar values (i.e., strings, numbers, true or false), and returns JSV_BAD_JSON if: + * the original JSON is not an array OR the JSON array contains non-scalar elements. + */ +bool json_get_array_items(const char *json, const char *json_end, int *value_type, std::vector &container); + +std::vector parse_histogram_from_json(const char *json); + +void test_parse_histogram_from_json(); + /* Currently there are only 3 persistent statistical tables */ static const uint STATISTICS_TABLES= 3; @@ -1651,84 +1664,82 @@ public: test_parse_histogram_from_json(); } - - static std::vector parse_histogram_from_json(const char *json) - { - std::vector hist_buckets= {}; - enum json_types vt = json_get_array_items(json, json + strlen(json), hist_buckets); - printf("%d", vt); - printf("%zu", hist_buckets.size()); - - return hist_buckets; - } - - static void test_parse_histogram_from_json() - { - std::vector bucket = {}; - std::string json; - std::string tests[7] = { - R"(["aabbb", "ccccdd", "eeefff"])", - R"(["aabbb", "ccc{}dd", "eeefff"])", - R"(["aabbb", {"a": "b"}, "eeefff"])", - R"({})", - R"([1,2,3, null])", - R"([null])", - R"([])" - }; - - for(const auto& test : tests) { - json = test; - bucket = parse_histogram_from_json(json.c_str()); - printf("%zu", bucket.size()); - } - } - - /* - * json_get_array_items expects a JSON array as argument, - * and pushes the elements of the array into the `container` vector. - * It only works if all the elements in the original JSON array - * are scalar values (i.e., strings, numbers, true or false), and returns JSV_BAD_JSON if: - * the original JSON is not an array OR the JSON array contains non-scalar elements. - */ - static json_types json_get_array_items(const char *json, const char *json_end, std::vector &container) { - json_engine_t je; - enum json_types value_type; - int vl; - const char *v; - - json_scan_start(&je, &my_charset_utf8mb4_bin, (const uchar *)json, (const uchar *)json_end); - - if (json_read_value(&je) || je.value_type != JSON_VALUE_ARRAY) - { - return JSV_BAD_JSON; - } - value_type = static_cast(je.value_type); - - std::string val; - while(!json_scan_next(&je)) - { - switch(je.state) - { - case JST_VALUE: - if (je.value_type != JSON_VALUE_STRING && - je.value_type != JSON_VALUE_NUMBER && - je.value_type != JSON_VALUE_TRUE && - je.value_type != JSON_VALUE_FALSE) - { - return JSV_BAD_JSON; - } - value_type = smart_read_value(&je, &v, &vl); - val = std::string(v, vl); - container.emplace_back(val); - case JST_ARRAY_END: - break; - } - } - - return value_type; - } }; +void test_parse_histogram_from_json() +{ + std::vector bucket = {}; + std::string json; + std::string tests[7] = { + R"(["aabbb", "ccccdd", "eeefff"])", + R"(["aabbb", "ccc{}dd", "eeefff"])", + R"(["aabbb", {"a": "b"}, "eeefff"])", + R"({})", + R"([1,2,3, null])", + R"([null])", + R"([])" + }; + + for(const auto& test : tests) { + json = test; + bucket = parse_histogram_from_json(json.c_str()); + } +} + +std::vector parse_histogram_from_json(const char *json) +{ + std::vector hist_buckets= {}; + int vt; + bool result = json_get_array_items(json, json + strlen(json), &vt, hist_buckets); + fprintf(stderr,"==============\n"); + fprintf(stderr,"histogram: %s\n", json); + fprintf(stderr, "json_get_array_items() returned %s\n", result ? "true" : "false"); + fprintf(stderr, "value type after json_get_array_items() is %d\n", vt); + fprintf(stderr, " JSV_BAD_JSON=%d, JSON_VALUE_ARRAY=%d\n", (int)JSV_BAD_JSON, (int)JSON_VALUE_ARRAY); + fprintf(stderr, "hist_buckets.size()=%zu\n", hist_buckets.size()); + + return hist_buckets; +} + +bool json_get_array_items(const char *json, const char *json_end, int *value_type, std::vector &container) { + json_engine_t je; + int vl; + const char *v; + + json_scan_start(&je, &my_charset_utf8mb4_bin, (const uchar *)json, (const uchar *)json_end); + + if (json_read_value(&je) || je.value_type != JSON_VALUE_ARRAY) + { + *value_type = JSV_BAD_JSON; + return false; + } + *value_type = je.value_type; + + std::string val; + while(!json_scan_next(&je)) + { + switch(je.state) + { + case JST_VALUE: + *value_type = json_smart_read_value(&je, &v, &vl); + if (je.value_type != JSON_VALUE_STRING && + je.value_type != JSON_VALUE_NUMBER && + je.value_type != JSON_VALUE_TRUE && + je.value_type != JSON_VALUE_FALSE) + { + *value_type = JSV_BAD_JSON; + return false; + } + val = std::string(v, vl); + container.emplace_back(val); + case JST_ARRAY_END: + break; + } + } + + return true; +} + C_MODE_START int histogram_build_walk(void *elem, element_count elem_cnt, void *arg) diff --git a/strings/json_lib.c b/strings/json_lib.c index 296fafad510..02e09acb8b1 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -1868,7 +1868,7 @@ int json_path_compare(const json_path_t *a, const json_path_t *b, } -enum json_types smart_read_value(json_engine_t *je, +enum json_types json_smart_read_value(json_engine_t *je, const char **value, int *value_len) { if (json_read_value(je)) @@ -1909,7 +1909,7 @@ enum json_types json_type(const char *js, const char *js_end, json_scan_start(&je, &my_charset_utf8mb4_bin,(const uchar *) js, (const uchar *) js_end); - return smart_read_value(&je, value, value_len); + return json_smart_read_value(&je, value, value_len); } @@ -1933,7 +1933,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end, { case JST_VALUE: if (c_item == n_item) - return smart_read_value(&je, value, value_len); + return json_smart_read_value(&je, value, value_len); if (json_skip_key(&je)) goto err_return; @@ -1997,7 +1997,7 @@ enum json_types json_get_object_key(const char *js, const char *js_end, json_string_set_str(&key_name, (const uchar *) key, (const uchar *) key_end); if (json_key_matches(&je, &key_name)) - return smart_read_value(&je, value, value_len); + return json_smart_read_value(&je, value, value_len); if (json_skip_key(&je)) goto err_return;