diff --git a/src/redis.c b/src/redis.c index 6e546ecc..41d74f4e 100644 --- a/src/redis.c +++ b/src/redis.c @@ -202,6 +202,7 @@ struct redisCommand redisCommandTable[] = { {"hincrbyfloat",hincrbyfloatCommand,4,"wmF",0,NULL,1,1,1,0,0}, {"hdel",hdelCommand,-3,"wF",0,NULL,1,1,1,0,0}, {"hlen",hlenCommand,2,"rF",0,NULL,1,1,1,0,0}, + {"hvstrlen",hvstrlenCommand,3,"rF",0,NULL,1,1,1,0,0}, {"hkeys",hkeysCommand,2,"rS",0,NULL,1,1,1,0,0}, {"hvals",hvalsCommand,2,"rS",0,NULL,1,1,1,0,0}, {"hgetall",hgetallCommand,2,"r",0,NULL,1,1,1,0,0}, diff --git a/src/redis.h b/src/redis.h index e248d290..142e830e 100644 --- a/src/redis.h +++ b/src/redis.h @@ -1516,6 +1516,7 @@ void hmsetCommand(redisClient *c); void hmgetCommand(redisClient *c); void hdelCommand(redisClient *c); void hlenCommand(redisClient *c); +void hvstrlenCommand(redisClient *c); void zremrangebyrankCommand(redisClient *c); void zunionstoreCommand(redisClient *c); void zinterstoreCommand(redisClient *c); diff --git a/src/t_hash.c b/src/t_hash.c index 7f33bba0..ea4f3a70 100644 --- a/src/t_hash.c +++ b/src/t_hash.c @@ -685,6 +685,20 @@ void hlenCommand(redisClient *c) { addReplyLongLong(c,hashTypeLength(o)); } +void hvstrlenCommand(redisClient *c) { + robj *o; + robj *value; + if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL || + checkType(c,o,REDIS_HASH)) return; + + if ((value = hashTypeGetObject(o,c->argv[2])) == NULL) { + addReply(c, shared.nullbulk); + } else { + addReplyLongLong(c,stringObjectLen(value)); + decrRefCount(value); + } +} + static void addHashIteratorCursorToReply(redisClient *c, hashTypeIterator *hi, int what) { if (hi->encoding == REDIS_ENCODING_ZIPLIST) { unsigned char *vstr = NULL; diff --git a/tests/unit/type/hash.tcl b/tests/unit/type/hash.tcl index fa52afd1..3d9be1fc 100644 --- a/tests/unit/type/hash.tcl +++ b/tests/unit/type/hash.tcl @@ -390,6 +390,37 @@ start_server {tags {"hash"}} { lappend rv [string match "ERR*not*float*" $bigerr] } {1 1} + test {HVSTRLEN against the small hash} { + set err {} + foreach k [array names smallhash *] { + if {[string length $smallhash($k)] ne [r hvstrlen smallhash $k]} { + set err "[string length $smallhash($k)] != [r hvstrlen smallhash $k]" + break + } + } + set _ $err + } {} + + test {HVSTRLEN against the big hash} { + set err {} + foreach k [array names bighash *] { + if {[string length $bighash($k)] ne [r hvstrlen bighash $k]} { + set err "[string length $bighash($k)] != [r hvstrlen bighash $k]" + break + } + } + set _ $err + } {} + + test {HVSTRLEN against non existing key} { + set rv {} + lappend rv [r hvstrlen smallhash __123123123__] + lappend rv [r hvstrlen bighash __123123123__] + set _ $rv + + } {{} {}} + + test {Hash ziplist regression test for large keys} { r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk a r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk b