summaryrefslogtreecommitdiff
path: root/sql/item_jsonfunc.cc
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2017-08-09 12:35:21 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2017-08-09 12:35:21 +0300
commit0930d6698fabc33a7b0dffaf13ff7a9e26fc6908 (patch)
treef229165bdbdcd8be17783904e53d3beadd69a902 /sql/item_jsonfunc.cc
parent1f0a22acbd906f391ed7ead6cad5ef50b89236c1 (diff)
parent6b14fd6d6d75e09b966ddb0750ccfbb94a74a909 (diff)
downloadmariadb-git-0930d6698fabc33a7b0dffaf13ff7a9e26fc6908.tar.gz
Merge 10.2 into bb-10.2-ext
Diffstat (limited to 'sql/item_jsonfunc.cc')
-rw-r--r--sql/item_jsonfunc.cc164
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: