diff options
-rw-r--r-- | mysql-test/r/func_json.result | 15 | ||||
-rw-r--r-- | mysql-test/t/func_json.test | 10 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 9 | ||||
-rw-r--r-- | sql/item_jsonfunc.cc | 111 | ||||
-rw-r--r-- | sql/item_jsonfunc.h | 4 | ||||
-rw-r--r-- | strings/json_lib.c | 2 |
6 files changed, 138 insertions, 13 deletions
diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index 894e46017f7..d004ebde35b 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -648,3 +648,18 @@ NULL SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*]' ); JSON_EXTRACT( '{"foo":"bar"}', '$[*]' ) NULL +select JSON_EXTRACT('{"name":"value"}', '$.name') = 'value'; +JSON_EXTRACT('{"name":"value"}', '$.name') = 'value' +1 +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = true; +JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = true +1 +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = false; +JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = false +0 +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1; +JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1 +1 +select JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"'); +JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"') +"\u00f6" diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index 0ce742aac11..3bcdc6a8709 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -302,3 +302,13 @@ DROP TABLE t1; SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*].*' ); SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*]' ); +# +# MDEV-12604 Comparison of JSON_EXTRACT result differs with Mysql. +# + +select JSON_EXTRACT('{"name":"value"}', '$.name') = 'value'; +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = true; +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = false; +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1; +select JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"'); + diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d203efa6305..efab3da4ac1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -670,6 +670,15 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg, &Arg_comparator::compare_datetime; } + if ((*a)->is_json_type() ^ (*b)->is_json_type()) + { + Item **j_item= (*a)->is_json_type() ? a : b; + Item *uf= new(thd->mem_root) Item_func_json_unquote(thd, *j_item); + if (!uf || uf->fix_fields(thd, &uf)) + return 1; + *j_item= uf; + } + a= cache_converted_constant(thd, a, &a_cache, m_compare_type); b= cache_converted_constant(thd, b, &b_cache, m_compare_type); return set_compare_func(owner_arg, m_compare_type); diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index c7639bc2513..3f001771e7c 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -587,24 +587,40 @@ void Item_func_json_unquote::fix_length_and_dec() } -String *Item_func_json_unquote::val_str(String *str) +String *Item_func_json_unquote::read_json(json_engine_t *je) { String *js= args[0]->val_json(&tmp_s); - json_engine_t je; - int c_len; if ((null_value= args[0]->null_value)) - return NULL; + return 0; - json_scan_start(&je, js->charset(),(const uchar *) js->ptr(), + json_scan_start(je, js->charset(),(const uchar *) js->ptr(), (const uchar *) js->ptr() + js->length()); - je.value_type= (enum json_value_types) -1; /* To report errors right. */ + je->value_type= (enum json_value_types) -1; /* To report errors right. */ - if (json_read_value(&je)) + if (json_read_value(je)) goto error; - if (je.value_type != JSON_VALUE_STRING) + return js; + +error: + if (je->value_type == JSON_VALUE_STRING) + report_json_error(js, je, 0); + return js; +} + + +String *Item_func_json_unquote::val_str(String *str) +{ + json_engine_t je; + int c_len; + String *js; + + if (!(js= read_json(&je))) + return NULL; + + if (je.s.error || je.value_type != JSON_VALUE_STRING) return js; str->length(0); @@ -621,13 +637,86 @@ String *Item_func_json_unquote::val_str(String *str) return str; error: - if (je.value_type == JSON_VALUE_STRING) - report_json_error(js, &je, 0); - /* We just return the argument's value in the case of error. */ + report_json_error(js, &je, 0); return js; } +double Item_func_json_unquote::val_real() +{ + json_engine_t je; + double d= 0.0; + String *js; + + if ((js= read_json(&je)) != NULL) + { + switch (je.value_type) + { + case JSON_VALUE_NUMBER: + { + char *end; + int err; + d= my_strntod(je.s.cs, (char *) je.value, je.value_len, &end, &err); + break; + } + case JSON_VALUE_TRUE: + d= 1.0; + break; + case JSON_VALUE_STRING: + { + char *end; + int err; + d= my_strntod(js->charset(), (char *) js->ptr(), js->length(), + &end, &err); + break; + } + default: + break; + }; + } + + return d; +} + + +longlong Item_func_json_unquote::val_int() +{ + json_engine_t je; + longlong i= 0; + String *js; + + if ((js= read_json(&je)) != NULL) + { + switch (je.value_type) + { + case JSON_VALUE_NUMBER: + { + char *end; + int err; + i= my_strntoll(je.s.cs, (char *) je.value, je.value_len, 10, + &end, &err); + break; + } + case JSON_VALUE_TRUE: + i= 1; + break; + case JSON_VALUE_STRING: + { + char *end; + int err; + i= my_strntoll(js->charset(), (char *) js->ptr(), js->length(), 10, + &end, &err); + break; + } + default: + break; + }; + } + + return i; +} + + static int alloc_tmp_paths(THD *thd, uint n_paths, json_path_with_flags **paths,String **tmp_paths) { diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h index 394ed5f189a..cc089129556 100644 --- a/sql/item_jsonfunc.h +++ b/sql/item_jsonfunc.h @@ -127,12 +127,14 @@ class Item_func_json_unquote: public Item_str_func { protected: String tmp_s; - + String *read_json(json_engine_t *je); public: Item_func_json_unquote(THD *thd, Item *s): Item_str_func(thd, s) {} const char *func_name() const { return "json_unquote"; } void fix_length_and_dec(); String *val_str(String *); + double val_real(); + longlong val_int(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_json_unquote>(thd, mem_root, this); } }; diff --git a/strings/json_lib.c b/strings/json_lib.c index 7167b6a2a54..b0c843caec1 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -253,7 +253,7 @@ static int read_4_hexdigits(json_string_t *s, uchar *dest) if ((c_len= json_next_char(s)) <= 0) return s->error= json_eos(s) ? JE_EOS : JE_BAD_CHR; - if (s->c_next >= 128 || (t= json_instr_chr_map[s->c_next]) >= S_F) + if (s->c_next >= 128 || (t= json_instr_chr_map[s->c_next]) > S_F) return s->error= JE_SYN; s->c_str+= c_len; |