diff options
author | Alexey Botchkov <holyfoot@askmonty.org> | 2017-08-08 15:40:11 +0400 |
---|---|---|
committer | Alexey Botchkov <holyfoot@askmonty.org> | 2017-08-08 15:40:11 +0400 |
commit | 4bca34d8a4d6e307ea9ee1d19c0aaf1e54df8837 (patch) | |
tree | 8b4050551e39b2436eaf225cb1a00648d53b1ceb /sql/item_jsonfunc.cc | |
parent | 01a4eb8f761eb669fe2ae5139c73a7434b141a8f (diff) | |
download | mariadb-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.cc | 50 |
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: |