summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/func_json.result15
-rw-r--r--mysql-test/t/func_json.test10
-rw-r--r--sql/item_cmpfunc.cc9
-rw-r--r--sql/item_jsonfunc.cc111
-rw-r--r--sql/item_jsonfunc.h4
-rw-r--r--strings/json_lib.c2
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;