summaryrefslogtreecommitdiff
path: root/sql/item_jsonfunc.cc
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2022-02-04 14:50:25 +0100
committerOleksandr Byelkin <sanja@mariadb.com>2022-02-04 14:50:25 +0100
commit4fb2cb1a30fc188682ae4dbda2f975213e5c3adf (patch)
tree522b2dc8096cc37ace66686de36b486b73a352f5 /sql/item_jsonfunc.cc
parentc0f5fd27549c84607defa64c5b651343dd29e0ee (diff)
parent9ed8deb656d9378fc9c1c7fb12c15674b6323ab0 (diff)
downloadmariadb-git-4fb2cb1a30fc188682ae4dbda2f975213e5c3adf.tar.gz
Merge branch '10.7' into 10.8
Diffstat (limited to 'sql/item_jsonfunc.cc')
-rw-r--r--sql/item_jsonfunc.cc92
1 files changed, 66 insertions, 26 deletions
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index fefb2a1c662..89ac59098ac 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, 2020, MariaDB Corporation.
+/* Copyright (c) 2016, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -133,16 +133,17 @@ static int json_nice(json_engine_t *je, String *nice_js,
Item_func_json_format::formats mode, int tab_size=4)
{
int depth= 0;
- const char *comma, *colon;
+ static const char *comma= ", ", *colon= "\": ";
uint comma_len, colon_len;
int first_value= 1;
- DBUG_ASSERT(je->s.cs == nice_js->charset());
+ nice_js->length(0);
+ nice_js->set_charset(je->s.cs);
+ nice_js->alloc(je->s.str_end - je->s.c_str + 32);
+
DBUG_ASSERT(mode != Item_func_json_format::DETAILED ||
(tab_size >= 0 && tab_size <= TAB_SIZE_LIMIT));
- comma= ", ";
- colon= "\": ";
if (mode == Item_func_json_format::LOOSE)
{
comma_len= 2;
@@ -239,7 +240,7 @@ handle_value:
};
} while (json_scan_next(je) == 0);
- return je->s.error;
+ return je->s.error || *je->killed_ptr;
error:
return 1;
@@ -933,8 +934,6 @@ String *Item_func_json_extract::read_json(String *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;
@@ -1512,6 +1511,32 @@ null_return:
}
+/*
+ This reproduces behavior according to the former
+ Item_func_conv_charset::is_json_type() which returned args[0]->is_json_type().
+ JSON functions with multiple string input with different character sets
+ wrap some arguments into Item_func_conv_charset. So the former
+ Item_func_conv_charset::is_json_type() took the JSON propery from args[0],
+ i.e. from the original argument before the conversion.
+ This is probably not always correct because an *explicit*
+ `CONVERT(arg USING charset)` is actually a general purpose string
+ expression, not a JSON expression.
+*/
+bool is_json_type(const Item *item)
+{
+ for ( ; ; )
+ {
+ if (Type_handler_json_common::is_json_type_handler(item->type_handler()))
+ return true;
+ const Item_func_conv_charset *func;
+ if (!(func= dynamic_cast<const Item_func_conv_charset*>(item)))
+ return false;
+ item= func->arguments()[0];
+ }
+ return false;
+}
+
+
static int append_json_value(String *str, Item *item, String *tmp_val)
{
if (item->type_handler()->is_bool_type())
@@ -1540,7 +1565,7 @@ static int append_json_value(String *str, Item *item, String *tmp_val)
String *sv= item->val_json(tmp_val);
if (item->null_value)
goto append_null;
- if (item->is_json_type())
+ if (is_json_type(item))
return str->append(sv->ptr(), sv->length());
if (item->result_type() == STRING_RESULT)
@@ -1586,7 +1611,7 @@ static int append_json_value_from_field(String *str,
String *sv= f->val_str(tmp_val, key + offset);
if (f->is_null_in_record(key))
goto append_null;
- if (i->is_json_type())
+ if (is_json_type(i))
return str->append(sv->ptr(), sv->length());
if (i->result_type() == STRING_RESULT)
@@ -1714,6 +1739,7 @@ String *Item_func_json_array_append::val_str(String *str)
uint n_arg, n_path;
size_t str_rest_len;
const uchar *ar_end;
+ THD *thd= current_thd;
DBUG_ASSERT(fixed());
@@ -1741,6 +1767,7 @@ String *Item_func_json_array_append::val_str(String *str)
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
+ je.killed_ptr= (uchar*)&thd->killed;
c_path->cur_step= c_path->p.steps;
@@ -1821,8 +1848,7 @@ String *Item_func_json_array_append::val_str(String *str)
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
- str->length(0);
- str->set_charset(js->charset());
+ je.killed_ptr= (uchar*)&thd->killed;
if (json_nice(&je, str, Item_func_json_format::LOOSE))
goto js_error;
@@ -1832,6 +1858,7 @@ js_error:
report_json_error(js, &je, 0);
return_null:
+ thd->check_killed(); // to get the error message right
null_value= 1;
return 0;
}
@@ -1842,6 +1869,7 @@ String *Item_func_json_array_insert::val_str(String *str)
json_engine_t je;
String *js= args[0]->val_json(&tmp_js);
uint n_arg, n_path;
+ THD *thd= current_thd;
DBUG_ASSERT(fixed());
@@ -1879,6 +1907,7 @@ String *Item_func_json_array_insert::val_str(String *str)
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
+ je.killed_ptr= (uchar*)&thd->killed;
c_path->cur_step= c_path->p.steps;
@@ -1918,7 +1947,7 @@ String *Item_func_json_array_insert::val_str(String *str)
goto js_error;
}
- if (unlikely(je.s.error))
+ if (unlikely(je.s.error || *je.killed_ptr))
goto js_error;
str->length(0);
@@ -1962,8 +1991,7 @@ String *Item_func_json_array_insert::val_str(String *str)
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
- str->length(0);
- str->set_charset(js->charset());
+ je.killed_ptr= (uchar*)&thd->killed;
if (json_nice(&je, str, Item_func_json_format::LOOSE))
goto js_error;
@@ -1972,6 +2000,7 @@ String *Item_func_json_array_insert::val_str(String *str)
js_error:
report_json_error(js, &je, 0);
return_null:
+ thd->check_killed(); // to get the error message right
null_value= 1;
return 0;
}
@@ -2130,8 +2159,7 @@ merged_j1:
return 2;
continue;
}
- if (json_skip_key(je2) ||
- json_skip_level(je1))
+ if (json_skip_key(je2) || json_skip_level(je1))
return 1;
goto continue_j2;
}
@@ -2231,6 +2259,7 @@ String *Item_func_json_merge::val_str(String *str)
json_engine_t je1, je2;
String *js1= args[0]->val_json(&tmp_js1), *js2=NULL;
uint n_arg;
+ THD *thd= current_thd;
LINT_INIT(js2);
if (args[0]->null_value)
@@ -2247,9 +2276,11 @@ 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());
+ je1.killed_ptr= (uchar*)&thd->killed;
json_scan_start(&je2, js2->charset(),(const uchar *) js2->ptr(),
(const uchar *) js2->ptr() + js2->length());
+ je2.killed_ptr= (uchar*)&thd->killed;
if (do_merge(str, &je1, &je2))
goto error_return;
@@ -2271,8 +2302,7 @@ 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());
+ je1.killed_ptr= (uchar*)&thd->killed;
if (json_nice(&je1, str, Item_func_json_format::LOOSE))
goto error_return;
@@ -2284,6 +2314,7 @@ error_return:
report_json_error(js1, &je1, 0);
if (je2.s.error)
report_json_error(js2, &je2, n_arg);
+ thd->check_killed(); // to get the error message right
null_return:
null_value= 1;
return NULL;
@@ -2533,6 +2564,7 @@ String *Item_func_json_merge_patch::val_str(String *str)
String *js1= args[0]->val_json(&tmp_js1), *js2=NULL;
uint n_arg;
bool empty_result, merge_to_null;
+ THD *thd= current_thd;
/* To report errors properly if some JSON is invalid. */
je1.s.error= je2.s.error= 0;
@@ -2549,6 +2581,7 @@ String *Item_func_json_merge_patch::val_str(String *str)
json_scan_start(&je2, js2->charset(),(const uchar *) js2->ptr(),
(const uchar *) js2->ptr() + js2->length());
+ je2.killed_ptr= (uchar*)&thd->killed;
if (merge_to_null)
{
@@ -2570,6 +2603,7 @@ String *Item_func_json_merge_patch::val_str(String *str)
json_scan_start(&je1, js1->charset(),(const uchar *) js1->ptr(),
(const uchar *) js1->ptr() + js1->length());
+ je1.killed_ptr= (uchar*)&thd->killed;
if (do_merge_patch(str, &je1, &je2, &empty_result))
goto error_return;
@@ -2598,8 +2632,7 @@ cont_point:
json_scan_start(&je1, js1->charset(),(const uchar *) js1->ptr(),
(const uchar *) js1->ptr() + js1->length());
- str->length(0);
- str->set_charset(js1->charset());
+ je1.killed_ptr= (uchar*)&thd->killed;
if (json_nice(&je1, str, Item_func_json_format::LOOSE))
goto error_return;
@@ -2611,6 +2644,7 @@ error_return:
report_json_error(js1, &je1, 0);
if (je2.s.error)
report_json_error(js2, &je2, n_arg);
+ thd->check_killed(); // to get the error message right
null_return:
null_value= 1;
return NULL;
@@ -2847,6 +2881,7 @@ String *Item_func_json_insert::val_str(String *str)
String *js= args[0]->val_json(&tmp_js);
uint n_arg, n_path;
json_string_t key_name;
+ THD *thd= current_thd;
DBUG_ASSERT(fixed());
@@ -2887,6 +2922,7 @@ String *Item_func_json_insert::val_str(String *str)
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
+ je.killed_ptr= (uchar*)&thd->killed;
if (c_path->p.last_step < c_path->p.steps)
goto v_found;
@@ -3068,7 +3104,7 @@ continue_point:
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
- str->length(0);
+ je.killed_ptr= (uchar*)&thd->killed;
if (json_nice(&je, str, Item_func_json_format::LOOSE))
goto js_error;
@@ -3076,6 +3112,7 @@ continue_point:
js_error:
report_json_error(js, &je, 0);
+ thd->check_killed(); // to get the error message right
return_null:
null_value= 1;
return 0;
@@ -3099,6 +3136,7 @@ String *Item_func_json_remove::val_str(String *str)
String *js= args[0]->val_json(&tmp_js);
uint n_arg, n_path;
json_string_t key_name;
+ THD *thd= current_thd;
DBUG_ASSERT(fixed());
@@ -3145,6 +3183,7 @@ String *Item_func_json_remove::val_str(String *str)
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
+ je.killed_ptr= (uchar*)&thd->killed;
c_path->cur_step= c_path->p.steps;
@@ -3253,8 +3292,7 @@ v_found:
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
- str->length(0);
- str->set_charset(js->charset());
+ je.killed_ptr= (uchar*)&thd->killed;
if (json_nice(&je, str, Item_func_json_format::LOOSE))
goto js_error;
@@ -3262,6 +3300,7 @@ v_found:
return str;
js_error:
+ thd->check_killed(); // to get the error message right
report_json_error(js, &je, 0);
null_return:
null_value= 1;
@@ -3652,6 +3691,7 @@ String *Item_func_json_format::val_str(String *str)
String *js= args[0]->val_json(&tmp_js);
json_engine_t je;
int tab_size= 4;
+ THD *thd= current_thd;
if ((null_value= args[0]->null_value))
return 0;
@@ -3675,13 +3715,13 @@ String *Item_func_json_format::val_str(String *str)
json_scan_start(&je, js->charset(), (const uchar *) js->ptr(),
(const uchar *) js->ptr()+js->length());
+ je.killed_ptr= (uchar*)&thd->killed;
- str->length(0);
- str->set_charset(js->charset());
if (json_nice(&je, str, fmt, tab_size))
{
null_value= 1;
report_json_error(js, &je, 0);
+ thd->check_killed(); // to get the error message right
return 0;
}