Commit bb71d9ab authored by Alexey Botchkov's avatar Alexey Botchkov

MDEV-12604 Comparison of JSON_EXTRACT result differs with Mysql.

        Comparison fixed to take the actual type of JSON value into
        account. Bug in escaping handling fixed.
parent 86e0a73e
......@@ -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"
......@@ -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\"');
......@@ -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);
......
......@@ -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)
{
......
......@@ -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); }
};
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment