diff --git a/src/db.c b/src/db.c index aded076b7..3d0a5ebca 100644 --- a/src/db.c +++ b/src/db.c @@ -33,6 +33,7 @@ #include "latency.h" #include "script.h" #include "functions.h" +#include "cluster.h" #include #include @@ -993,13 +994,22 @@ void randomkeyCommand(client *c) { void keysCommand(client *c) { dictEntry *de; sds pattern = c->argv[1]->ptr; - int plen = sdslen(pattern), allkeys; + int plen = sdslen(pattern), allkeys, pslot = -1; long numkeys = 0; void *replylen = addReplyDeferredLen(c); - dbIterator *dbit = dbIteratorInit(c->db, DB_MAIN); allkeys = (pattern[0] == '*' && plen == 1); + if (!allkeys) { + pslot = patternHashSlot(pattern, plen); + } + dictIterator *di = NULL; + dbIterator *dbit = NULL; + if (server.cluster_enabled && !allkeys && pslot != -1) { + di = dictGetSafeIterator(c->db->dict[pslot]); + } else { + dbit = dbIteratorInit(c->db, DB_MAIN); + } robj keyobj; - while ((de = dbIteratorNext(dbit)) != NULL) { + while ((de = di ? dictNext(di) : dbIteratorNext(dbit)) != NULL) { sds key = dictGetKey(de); if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) { @@ -1012,7 +1022,10 @@ void keysCommand(client *c) { if (c->flags & CLIENT_CLOSE_ASAP) break; } - dbReleaseIterator(dbit); + if (di) + dictReleaseIterator(di); + if (dbit) + dbReleaseIterator(dbit); setDeferredArrayLen(c,replylen,numkeys); } diff --git a/tests/unit/keyspace.tcl b/tests/unit/keyspace.tcl index 0769dbf3e..31130e4c6 100644 --- a/tests/unit/keyspace.tcl +++ b/tests/unit/keyspace.tcl @@ -34,6 +34,14 @@ start_server {tags {"keyspace"}} { r dbsize } {6} + test {KEYS with hashtag} { + foreach key {"{a}x" "{a}y" "{a}z" "{b}a" "{b}b" "{b}c"} { + r set $key hello + } + assert_equal [lsort [r keys "{a}*"]] [list "{a}x" "{a}y" "{a}z"] + assert_equal [lsort [r keys "*{b}*"]] [list "{b}a" "{b}b" "{b}c"] + } + test {DEL all keys} { foreach key [r keys *] {r del $key} r dbsize