summaryrefslogtreecommitdiff
path: root/sql/item_jsonfunc.cc
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2017-08-08 15:40:11 +0400
committerAlexey Botchkov <holyfoot@askmonty.org>2017-08-08 15:40:11 +0400
commit4bca34d8a4d6e307ea9ee1d19c0aaf1e54df8837 (patch)
tree8b4050551e39b2436eaf225cb1a00648d53b1ceb /sql/item_jsonfunc.cc
parent01a4eb8f761eb669fe2ae5139c73a7434b141a8f (diff)
downloadmariadb-git-4bca34d8a4d6e307ea9ee1d19c0aaf1e54df8837.tar.gz
MDEV-12789 JSON_KEYS returns duplicate keys twice.
Check for duplicating keys added.
Diffstat (limited to 'sql/item_jsonfunc.cc')
-rw-r--r--sql/item_jsonfunc.cc50
1 files changed, 46 insertions, 4 deletions
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index 315443fdcd2..d871175a3ba 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -2779,6 +2779,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;
@@ -2835,6 +2870,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)
{
@@ -2844,13 +2880,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: