mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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.
This commit is contained in:
@ -648,3 +648,18 @@ NULL
|
|||||||
SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*]' );
|
SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*]' );
|
||||||
JSON_EXTRACT( '{"foo":"bar"}', '$[*]' )
|
JSON_EXTRACT( '{"foo":"bar"}', '$[*]' )
|
||||||
NULL
|
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"}', '$[*].*' );
|
||||||
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;
|
&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);
|
a= cache_converted_constant(thd, a, &a_cache, m_compare_type);
|
||||||
b= cache_converted_constant(thd, b, &b_cache, m_compare_type);
|
b= cache_converted_constant(thd, b, &b_cache, m_compare_type);
|
||||||
return set_compare_func(owner_arg, 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);
|
String *js= args[0]->val_json(&tmp_s);
|
||||||
json_engine_t je;
|
|
||||||
int c_len;
|
|
||||||
|
|
||||||
if ((null_value= args[0]->null_value))
|
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());
|
(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;
|
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;
|
return js;
|
||||||
|
|
||||||
str->length(0);
|
str->length(0);
|
||||||
@ -621,13 +637,86 @@ String *Item_func_json_unquote::val_str(String *str)
|
|||||||
return str;
|
return str;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (je.value_type == JSON_VALUE_STRING)
|
report_json_error(js, &je, 0);
|
||||||
report_json_error(js, &je, 0);
|
|
||||||
/* We just return the argument's value in the case of error. */
|
|
||||||
return js;
|
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,
|
static int alloc_tmp_paths(THD *thd, uint n_paths,
|
||||||
json_path_with_flags **paths,String **tmp_paths)
|
json_path_with_flags **paths,String **tmp_paths)
|
||||||
{
|
{
|
||||||
|
@ -127,12 +127,14 @@ class Item_func_json_unquote: public Item_str_func
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
String tmp_s;
|
String tmp_s;
|
||||||
|
String *read_json(json_engine_t *je);
|
||||||
public:
|
public:
|
||||||
Item_func_json_unquote(THD *thd, Item *s): Item_str_func(thd, s) {}
|
Item_func_json_unquote(THD *thd, Item *s): Item_str_func(thd, s) {}
|
||||||
const char *func_name() const { return "json_unquote"; }
|
const char *func_name() const { return "json_unquote"; }
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
String *val_str(String *);
|
String *val_str(String *);
|
||||||
|
double val_real();
|
||||||
|
longlong val_int();
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
{ return get_item_copy<Item_func_json_unquote>(thd, mem_root, this); }
|
{ 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)
|
if ((c_len= json_next_char(s)) <= 0)
|
||||||
return s->error= json_eos(s) ? JE_EOS : JE_BAD_CHR;
|
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;
|
return s->error= JE_SYN;
|
||||||
|
|
||||||
s->c_str+= c_len;
|
s->c_str+= c_len;
|
||||||
|
Reference in New Issue
Block a user