diff options
Diffstat (limited to 'sql/item_jsonfunc.cc')
-rw-r--r-- | sql/item_jsonfunc.cc | 164 |
1 files changed, 148 insertions, 16 deletions
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 9e9b26e2119..bdfce15b137 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -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) { @@ -1397,6 +1486,8 @@ void Item_func_json_array::fix_length_and_dec() ulonglong char_length= 2; uint n_arg; + result_limit= 0; + if (arg_count == 0) { collation.set(&my_charset_utf8_general_ci); @@ -1413,7 +1504,6 @@ void Item_func_json_array::fix_length_and_dec() fix_char_length_ulonglong(char_length); tmp_val.set_charset(collation.collation); - result_limit= 0; } @@ -2692,6 +2782,41 @@ void Item_func_json_keys::fix_length_and_dec() } +/* + That function is for Item_func_json_keys::val_str exclusively. + It utilizes the fact the resulting string is in specific format: + ["key1", "key2"...] +*/ +static int check_key_in_list(String *res, + const uchar *key, int key_len) +{ + const uchar *c= (const uchar *) res->ptr() + 2; /* beginning '["' */ + const uchar *end= (const uchar *) res->end() - 1; /* ending '"' */ + + while (c < end) + { + int n_char; + for (n_char=0; c[n_char] != '"' && n_char < key_len; n_char++) + { + if (c[n_char] != key[n_char]) + break; + } + if (c[n_char] == '"') + { + if (n_char == key_len) + return 1; + } + else + { + while (c[n_char] != '"') + n_char++; + } + c+= n_char + 4; /* skip ', "' */ + } + return 0; +} + + String *Item_func_json_keys::val_str(String *str) { json_engine_t je; @@ -2748,6 +2873,7 @@ skip_search: while (json_scan_next(&je) == 0 && je.state != JST_OBJ_END) { const uchar *key_start, *key_end; + int key_len; switch (je.state) { @@ -2757,13 +2883,19 @@ skip_search: { key_end= je.s.c_str; } while (json_read_keyname_chr(&je) == 0); - if (je.s.error || - (n_keys > 0 && str->append(", ", 2)) || + if (je.s.error) + goto err_return; + key_len= key_end - key_start; + + if (!check_key_in_list(str, key_start, key_len)) + { + if ((n_keys > 0 && str->append(", ", 2)) || str->append("\"", 1) || - append_simple(str, key_start, key_end - key_start) || + append_simple(str, key_start, key_len) || str->append("\"", 1)) goto err_return; - n_keys++; + n_keys++; + } break; case JST_OBJ_START: case JST_ARRAY_START: |