1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

MDEV-11557 port MySQL-5.7 JSON tests to MariaDB.

Fixes for issues found.
This commit is contained in:
Alexey Botchkov
2017-02-06 06:47:48 +04:00
parent e51b015fc3
commit abf7582112
8 changed files with 639 additions and 220 deletions

View File

@ -113,6 +113,100 @@ static int st_append_escaped(String *s, const String *a)
}
static int json_nice(json_engine_t *je, String *nice_js,
Item_func_json_format::formats mode)
{
int depth= 0;
const char *comma, *colon;
uint comma_len, colon_len;
int first_value= 1;
DBUG_ASSERT(je->s.cs == nice_js->charset());
if (mode == Item_func_json_format::LOOSE)
{
comma= ", ";
comma_len= 2;
colon= "\": ";
colon_len= 3;
}
else
{
comma= ",";
comma_len= 1;
colon= "\":";
colon_len= 2;
}
do
{
switch (je->state)
{
case JST_KEY:
{
const uchar *key_start= je->s.c_str;
const uchar *key_end;
while (json_read_keyname_chr(je) == 0)
key_end= je->s.c_str;
if (je->s.error)
goto error;
if (!first_value)
nice_js->append(comma, comma_len);
nice_js->append("\"", 1);
append_simple(nice_js, key_start, key_end - key_start);
nice_js->append(colon, colon_len);
}
/* now we have key value to handle, so no 'break'. */
DBUG_ASSERT(je->state == JST_VALUE);
goto handle_value;
case JST_VALUE:
if (!first_value)
nice_js->append(comma, comma_len);
handle_value:
if (json_read_value(je))
goto error;
if (json_value_scalar(je))
{
if (append_simple(nice_js, je->value_begin,
je->value_end - je->value_begin))
goto error;
first_value= 0;
}
else
{
nice_js->append((je->value_type == JSON_VALUE_OBJECT) ? "{" : "[", 1);
first_value= 1;
depth++;
}
break;
case JST_OBJ_END:
case JST_ARRAY_END:
depth--;
nice_js->append((je->state == JST_OBJ_END) ? "}": "]", 1);
first_value= 0;
break;
default:
break;
};
} while (json_scan_next(je) == 0);
return je->s.error;
error:
return 1;
}
#define report_json_error(js, je, n_param) \
report_json_error_ex(js, je, func_name(), n_param, \
Sql_condition::WARN_LEVEL_WARN)
@ -554,11 +648,11 @@ void Item_func_json_extract::fix_length_and_dec()
static bool path_exact(const json_path_with_flags *paths_list, int n_paths,
const json_path_t *p)
const json_path_t *p, enum json_value_types vt)
{
for (; n_paths > 0; n_paths--, paths_list++)
{
if (json_path_compare(&paths_list->p, p) == 0)
if (json_path_compare(&paths_list->p, p, vt) == 0)
return TRUE;
}
return FALSE;
@ -566,11 +660,11 @@ static bool path_exact(const json_path_with_flags *paths_list, int n_paths,
static bool path_ok(const json_path_with_flags *paths_list, int n_paths,
const json_path_t *p)
const json_path_t *p, enum json_value_types vt)
{
for (; n_paths > 0; n_paths--, paths_list++)
{
if (json_path_compare(&paths_list->p, p) >= 0)
if (json_path_compare(&paths_list->p, p, vt) >= 0)
return TRUE;
}
return FALSE;
@ -624,7 +718,7 @@ String *Item_func_json_extract::val_str(String *str)
while (json_get_path_next(&je, &p) == 0)
{
if (!path_exact(paths, arg_count-1, &p))
if (!path_exact(paths, arg_count-1, &p, je.value_type))
continue;
value= je.value_begin;
@ -661,10 +755,18 @@ String *Item_func_json_extract::val_str(String *str)
goto return_null;
}
if (possible_multiple_values && str->append("]"))
if (possible_multiple_values && str->append("]", 1))
goto error; /* Out of memory. */
return str;
js= str;
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
tmp_js.length(0);
tmp_js.set_charset(js->charset());
if (json_nice(&je, &tmp_js, Item_func_json_format::LOOSE))
goto error;
return &tmp_js;
error:
report_json_error(js, &je, 0);
@ -1153,7 +1255,7 @@ longlong Item_func_json_contains_path::val_int()
json_path_with_flags *c_path= paths;
for (; n_path > 0; n_path--, c_path++)
{
if (json_path_compare(&c_path->p, &p) >= 0)
if (json_path_compare(&c_path->p, &p, je.value_type) >= 0)
{
if (mode_one)
{
@ -1424,7 +1526,14 @@ String *Item_func_json_array_append::val_str(String *str)
}
}
return js;
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
str->length(0);
str->set_charset(js->charset());
if (json_nice(&je, str, Item_func_json_format::LOOSE))
goto js_error;
return str;
js_error:
report_json_error(js, &je, 0);
@ -1558,7 +1667,14 @@ String *Item_func_json_array_insert::val_str(String *str)
}
}
return js;
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
str->length(0);
str->set_charset(js->charset());
if (json_nice(&je, str, Item_func_json_format::LOOSE))
goto js_error;
return str;
js_error:
report_json_error(js, &je, 0);
@ -1690,8 +1806,15 @@ String *Item_func_json_merge::val_str(String *str)
}
}
json_scan_start(&je1, js1->charset(),(const uchar *) js1->ptr(),
(const uchar *) js1->ptr() + js1->length());
str->length(0);
str->set_charset(js1->charset());
if (json_nice(&je1, str, Item_func_json_format::LOOSE))
goto error_return;
null_value= 0;
return js1;
return str;
error_return:
if (je1.s.error)
@ -1970,6 +2093,7 @@ String *Item_func_json_insert::val_str(String *str)
{
if (je.s.error)
goto js_error;
continue;
}
if (json_read_value(&je))
@ -1986,7 +2110,16 @@ String *Item_func_json_insert::val_str(String *str)
int do_array_autowrap;
if (mode_insert)
do_array_autowrap= !mode_replace || lp->n_item;
{
if (mode_replace)
do_array_autowrap= lp->n_item > 0;
else
{
if (lp->n_item == 0)
continue;
do_array_autowrap= 1;
}
}
else
{
if (lp->n_item)
@ -2124,7 +2257,14 @@ continue_point:
}
}
return js;
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
str->length(0);
str->set_charset(js->charset());
if (json_nice(&je, str, Item_func_json_format::LOOSE))
goto js_error;
return str;
js_error:
report_json_error(js, &je, 0);
@ -2300,7 +2440,14 @@ v_found:
}
}
return js;
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
str->length(0);
str->set_charset(js->charset());
if (json_nice(&je, str, Item_func_json_format::LOOSE))
goto js_error;
return str;
js_error:
report_json_error(js, &je, 0);
@ -2540,7 +2687,7 @@ String *Item_func_json_search::val_str(String *str)
{
if (json_value_scalar(&je))
{
if ((arg_count < 5 || path_ok(paths, arg_count - 4, &p)) &&
if ((arg_count < 5 || path_ok(paths, arg_count - 4, &p, je.value_type)) &&
compare_json_value_wild(&je, s_str) != 0)
{
++n_path_found;
@ -2609,3 +2756,52 @@ String *Item_json_typecast::val_str(String *str)
return vs;
}
const char *Item_func_json_format::func_name() const
{
switch (fmt)
{
case COMPACT:
return "json_compact";
case LOOSE:
return "json_loose";
case DETAILED:
return "json_detailed";
default:
DBUG_ASSERT(0);
};
return "";
}
void Item_func_json_format::fix_length_and_dec()
{
decimals= 0;
max_length= args[0]->max_length;
}
String *Item_func_json_format::val_str(String *str)
{
String *js= args[0]->val_str(&tmp_js);
json_engine_t je;
if ((null_value= args[0]->null_value))
return 0;
json_scan_start(&je, js->charset(), (const uchar *) js->ptr(),
(const uchar *) js->ptr()+js->length());
str->length(0);
str->set_charset(js->charset());
if (json_nice(&je, str, fmt))
{
null_value= 1;
report_json_error(js, &je, 0);
return 0;
}
return str;
}