diff options
author | Alexander Barkov <bar@mariadb.com> | 2019-06-28 12:35:02 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2019-06-28 12:35:02 +0400 |
commit | 323a87b591d3e9bcedb7dea09b69d9eeb1c42880 (patch) | |
tree | 6562f42e84209dd655edb8a2a8c66d5e5b992116 | |
parent | cff7cf15d7a089639ed0fb2ad038e023cce49df5 (diff) | |
download | mariadb-git-323a87b591d3e9bcedb7dea09b69d9eeb1c42880.tar.gz |
MDEV-19888 Add abstract class Item_json_func
-rw-r--r-- | sql/item_jsonfunc.cc | 95 | ||||
-rw-r--r-- | sql/item_jsonfunc.h | 101 |
2 files changed, 123 insertions, 73 deletions
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index a90e7fb3a1a..14bffc998e3 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -439,7 +439,17 @@ bool Item_func_json_value::fix_length_and_dec() { collation.set(args[0]->collation); max_length= args[0]->max_length; - path.set_constant_flag(args[1]->const_item()); + set_constant_flag(args[1]->const_item()); + maybe_null= 1; + return FALSE; +} + + +bool Item_func_json_query::fix_length_and_dec() +{ + collation.set(args[0]->collation); + max_length= args[0]->max_length; + set_constant_flag(args[1]->const_item()); maybe_null= 1; return FALSE; } @@ -449,115 +459,100 @@ bool Item_func_json_value::fix_length_and_dec() Returns NULL, not an error if the found value is not a scalar. */ -String *Item_func_json_value::val_str(String *str) +bool Json_path_extractor::extract(String *str, Item *item_js, Item *item_jp, + CHARSET_INFO *cs) { - json_engine_t je; - String *js= args[0]->val_json(&tmp_js); + String *js= item_js->val_json(&tmp_js); int error= 0; uint array_counters[JSON_DEPTH_LIMIT]; - if (!path.parsed) + if (!parsed) { - String *s_p= args[1]->val_str(&tmp_path); + String *s_p= item_jp->val_str(&tmp_path); if (s_p && - json_path_setup(&path.p, s_p->charset(), (const uchar *) s_p->ptr(), + json_path_setup(&p, s_p->charset(), (const uchar *) s_p->ptr(), (const uchar *) s_p->ptr() + s_p->length())) - goto err_return; - path.parsed= path.constant; + return true; + parsed= constant; } - if ((null_value= args[0]->null_value || args[1]->null_value)) - return NULL; - - json_scan_start(&je, js->charset(),(const uchar *) js->ptr(), - (const uchar *) js->ptr() + js->length()); + if (item_js->null_value || item_jp->null_value) + return true; + Json_engine_scan je(*js); str->length(0); - str->set_charset(collation.collation); + str->set_charset(cs); - path.cur_step= path.p.steps; + cur_step= p.steps; continue_search: - if (json_find_path(&je, &path.p, &path.cur_step, array_counters)) - { - if (je.s.error) - goto err_return; - - null_value= 1; - return 0; - } + if (json_find_path(&je, &p, &cur_step, array_counters)) + return true; if (json_read_value(&je)) - goto err_return; + return true; if (unlikely(check_and_get_value(&je, str, &error))) { if (error) - goto err_return; + return true; goto continue_search; } - return str; - -err_return: - null_value= 1; - return 0; + return false; } -bool Item_func_json_value::check_and_get_value(json_engine_t *je, String *res, - int *error) +bool Json_engine_scan::check_and_get_value_scalar(String *res, int *error) { CHARSET_INFO *json_cs; const uchar *js; uint js_len; - if (!json_value_scalar(je)) + if (!json_value_scalar(this)) { /* We only look for scalar values! */ - if (json_skip_level(je) || json_scan_next(je)) + if (json_skip_level(this) || json_scan_next(this)) *error= 1; return true; } - if (je->value_type == JSON_VALUE_TRUE || - je->value_type == JSON_VALUE_FALSE) + if (value_type == JSON_VALUE_TRUE || + value_type == JSON_VALUE_FALSE) { json_cs= &my_charset_utf8mb4_bin; - js= (const uchar *) ((je->value_type == JSON_VALUE_TRUE) ? "1" : "0"); + js= (const uchar *) ((value_type == JSON_VALUE_TRUE) ? "1" : "0"); js_len= 1; } else { - json_cs= je->s.cs; - js= je->value; - js_len= je->value_len; + json_cs= s.cs; + js= value; + js_len= value_len; } - return st_append_json(res, json_cs, js, js_len); + return st_append_json(res, json_cs, js, js_len); } -bool Item_func_json_query::check_and_get_value(json_engine_t *je, String *res, - int *error) +bool Json_engine_scan::check_and_get_value_complex(String *res, int *error) { - const uchar *value; - if (json_value_scalar(je)) + if (json_value_scalar(this)) { /* We skip scalar values. */ - if (json_scan_next(je)) + if (json_scan_next(this)) *error= 1; return true; } - value= je->value; - if (json_skip_level(je)) + const uchar *tmp_value= value; + if (json_skip_level(this)) { *error= 1; return true; } - res->set((const char *) je->value, (uint32)(je->s.c_str - value), je->s.cs); + res->set((const char *) value, (uint32)(s.c_str - tmp_value), s.cs); return false; } diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h index e9b77502e80..a9e6f39b5c8 100644 --- a/sql/item_jsonfunc.h +++ b/sql/item_jsonfunc.h @@ -40,6 +40,33 @@ public: }; +class Json_engine_scan: public json_engine_t +{ +public: + Json_engine_scan(CHARSET_INFO *i_cs, const uchar *str, const uchar *end) + { + json_scan_start(this, i_cs, str, end); + } + Json_engine_scan(const String &str) + :Json_engine_scan(str.charset(), (const uchar *) str.ptr(), + (const uchar *) str.end()) + { } + bool check_and_get_value_scalar(String *res, int *error); + bool check_and_get_value_complex(String *res, int *error); +}; + + +class Json_path_extractor: public json_path_with_flags +{ +protected: + String tmp_js, tmp_path; + virtual ~Json_path_extractor() { } + virtual bool check_and_get_value(Json_engine_scan *je, + String *to, int *error)=0; + bool extract(String *to, Item *js, Item *jp, CHARSET_INFO *cs); +}; + + class Item_func_json_valid: public Item_bool_func { protected: @@ -78,32 +105,65 @@ public: }; -class Item_func_json_value: public Item_str_func +class Item_json_func: public Item_str_func +{ +public: + Item_json_func(THD *thd) + :Item_str_func(thd) { } + Item_json_func(THD *thd, Item *a) + :Item_str_func(thd, a) { } + Item_json_func(THD *thd, Item *a, Item *b) + :Item_str_func(thd, a, b) { } + Item_json_func(THD *thd, List<Item> &list) + :Item_str_func(thd, list) { } + bool is_json_type() { return true; } +}; + + +class Item_func_json_value: public Item_str_func, + public Json_path_extractor { -protected: - json_path_with_flags path; - String tmp_js, tmp_path; public: Item_func_json_value(THD *thd, Item *js, Item *i_path): Item_str_func(thd, js, i_path) {} const char *func_name() const { return "json_value"; } bool fix_length_and_dec(); - String *val_str(String *); - virtual bool check_and_get_value(json_engine_t *je, String *res, int *error); + String *val_str(String *to) + { + null_value= Json_path_extractor::extract(to, args[0], args[1], + collation.collation); + return null_value ? NULL : to; + } + bool check_and_get_value(Json_engine_scan *je, + String *res, int *error) override + { + return je->check_and_get_value_scalar(res, error); + } Item *get_copy(THD *thd) { return get_item_copy<Item_func_json_value>(thd, this); } }; -class Item_func_json_query: public Item_func_json_value +class Item_func_json_query: public Item_json_func, + public Json_path_extractor { public: Item_func_json_query(THD *thd, Item *js, Item *i_path): - Item_func_json_value(thd, js, i_path) {} - bool is_json_type() { return true; } + Item_json_func(thd, js, i_path) {} const char *func_name() const { return "json_query"; } - bool check_and_get_value(json_engine_t *je, String *res, int *error); + bool fix_length_and_dec(); + String *val_str(String *to) + { + null_value= Json_path_extractor::extract(to, args[0], args[1], + collation.collation); + return null_value ? NULL : to; + } + bool check_and_get_value(Json_engine_scan *je, + String *res, int *error) override + { + return je->check_and_get_value_complex(res, error); + } Item *get_copy(THD *thd) { return get_item_copy<Item_func_json_query>(thd, this); } }; @@ -139,18 +199,17 @@ public: }; -class Item_json_str_multipath: public Item_str_func +class Item_json_str_multipath: public Item_json_func { protected: json_path_with_flags *paths; String *tmp_paths; public: Item_json_str_multipath(THD *thd, List<Item> &list): - Item_str_func(thd, list), tmp_paths(0) {} + Item_json_func(thd, list), tmp_paths(0) {} bool fix_fields(THD *thd, Item **ref); void cleanup(); virtual uint get_n_paths() const = 0; - bool is_json_type() { return true; } }; @@ -217,18 +276,17 @@ public: }; -class Item_func_json_array: public Item_str_func +class Item_func_json_array: public Item_json_func { protected: String tmp_val; ulong result_limit; public: Item_func_json_array(THD *thd): - Item_str_func(thd) {} + Item_json_func(thd) {} Item_func_json_array(THD *thd, List<Item> &list): - Item_str_func(thd, list) {} + Item_json_func(thd, list) {} String *val_str(String *); - bool is_json_type() { return true; } bool fix_length_and_dec(); const char *func_name() const { return "json_array"; } Item *get_copy(THD *thd) @@ -273,7 +331,6 @@ public: Item_func_json_object(THD *thd, List<Item> &list): Item_func_json_array(thd, list) {} String *val_str(String *); - bool is_json_type() { return true; } const char *func_name() const { return "json_object"; } Item *get_copy(THD *thd) { return get_item_copy<Item_func_json_object>(thd, this); } @@ -288,7 +345,6 @@ public: Item_func_json_merge(THD *thd, List<Item> &list): Item_func_json_array(thd, list) {} String *val_str(String *); - bool is_json_type() { return true; } const char *func_name() const { return "json_merge_preserve"; } Item *get_copy(THD *thd) { return get_item_copy<Item_func_json_merge>(thd, this); } @@ -439,7 +495,7 @@ public: }; -class Item_func_json_format: public Item_str_func +class Item_func_json_format: public Item_json_func { public: enum formats @@ -454,15 +510,14 @@ protected: String tmp_js; public: Item_func_json_format(THD *thd, Item *js, formats format): - Item_str_func(thd, js), fmt(format) {} + Item_json_func(thd, js), fmt(format) {} Item_func_json_format(THD *thd, List<Item> &list): - Item_str_func(thd, list), fmt(DETAILED) {} + Item_json_func(thd, list), fmt(DETAILED) {} const char *func_name() const; bool fix_length_and_dec(); String *val_str(String *str); String *val_json(String *str); - bool is_json_type() { return true; } Item *get_copy(THD *thd) { return get_item_copy<Item_func_json_format>(thd, this); } }; |