diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2022-02-04 14:50:25 +0100 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2022-02-04 14:50:25 +0100 |
commit | 4fb2cb1a30fc188682ae4dbda2f975213e5c3adf (patch) | |
tree | 522b2dc8096cc37ace66686de36b486b73a352f5 /sql/item_jsonfunc.cc | |
parent | c0f5fd27549c84607defa64c5b651343dd29e0ee (diff) | |
parent | 9ed8deb656d9378fc9c1c7fb12c15674b6323ab0 (diff) | |
download | mariadb-git-4fb2cb1a30fc188682ae4dbda2f975213e5c3adf.tar.gz |
Merge branch '10.7' into 10.8
Diffstat (limited to 'sql/item_jsonfunc.cc')
-rw-r--r-- | sql/item_jsonfunc.cc | 92 |
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; } |