Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added ZPOP and ZREVPOP

  • Loading branch information...
commit dfd5dc2792bc988bba0191e7e1657a4931e48308 1 parent 04a2ade
Beau Harrington authored
12 src/help.h
View
@@ -632,7 +632,17 @@ struct commandHelp {
"destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]",
"Add multiple sorted sets and store the resulting sorted set in a new key",
4,
- "1.3.10" }
+ "1.3.10" },
+ { "ZPOP",
+ "key [minscore]",
+ "Remove and get the highest ranked member of a sorted set",
+ 4,
+ "2.1.11" },
+ { "ZREVPOP",
+ "key [maxscore]",
+ "Remove and get the lowest ranked member of a sorted set",
+ 4,
+ "2.1.11" }
};
#endif
2  src/redis.c
View
@@ -132,6 +132,8 @@ struct redisCommand readonlyCommandTable[] = {
{"zscore",zscoreCommand,3,0,NULL,1,1,1},
{"zrank",zrankCommand,3,0,NULL,1,1,1},
{"zrevrank",zrevrankCommand,3,0,NULL,1,1,1},
+ {"zpop",zpopCommand,-2,0,NULL,1,1,1},
+ {"zrevpop",zrevpopCommand,-2,0,NULL,1,1,1},
{"hset",hsetCommand,4,REDIS_CMD_DENYOOM,NULL,1,1,1},
{"hsetnx",hsetnxCommand,4,REDIS_CMD_DENYOOM,NULL,1,1,1},
{"hget",hgetCommand,3,0,NULL,1,1,1},
2  src/redis.h
View
@@ -998,6 +998,8 @@ void hlenCommand(redisClient *c);
void zremrangebyrankCommand(redisClient *c);
void zunionstoreCommand(redisClient *c);
void zinterstoreCommand(redisClient *c);
+void zpopCommand(redisClient *c);
+void zrevpopCommand(redisClient *c);
void hkeysCommand(redisClient *c);
void hvalsCommand(redisClient *c);
void hgetallCommand(redisClient *c);
56 src/t_zset.c
View
@@ -1058,3 +1058,59 @@ void zrankCommand(redisClient *c) {
void zrevrankCommand(redisClient *c) {
zrankGenericCommand(c, 1);
}
+
+void zpopGenericCommand(redisClient *c, int reverse) {
+ robj *o;
+ zset *zs;
+ zskiplist *zsl;
+ zskiplistNode *ln;
+ int withminscore = 0;
+ double minscore;
+
+ o = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk);
+ if (o == NULL || checkType(c,o,REDIS_ZSET)) return;
+
+ if(c->argc == 3) {
+ withminscore = 1;
+ if (getDoubleFromObjectOrReply(c, c->argv[2], &minscore, NULL) != REDIS_OK) return;
+ } else if (c->argc > 3) {
+ addReply(c,shared.syntaxerr);
+ return;
+ }
+
+ zs = o->ptr;
+ zsl = zs->zsl;
+ if (reverse) {
+ ln = zsl->header->level[0].forward;
+ } else {
+ ln = zsl->tail;
+ };
+
+ if (ln == NULL) {
+ addReply(c,shared.nullbulk);
+ } else if (withminscore && (reverse ? ln->score > minscore : ln->score < minscore)) {
+ addReply(c,shared.nullbulk);
+ } else {
+ addReplyBulk(c,ln->obj);
+
+ long deleted;
+ deleted = zslDelete(zsl,ln->score,ln->obj);
+ redisAssert(deleted != 0);
+
+ /* Delete from the hash table */
+ dictDelete(zs->dict,ln->obj);
+ if (htNeedsResize(zs->dict)) dictResize(zs->dict);
+ if (dictSize(zs->dict) == 0) dbDelete(c->db,c->argv[1]);
+
+ touchWatchedKey(c->db,c->argv[1]);
+ server.dirty++;
+ }
+}
+
+void zpopCommand(redisClient *c) {
+ zpopGenericCommand(c, 0);
+}
+
+void zrevpopCommand(redisClient *c) {
+ zpopGenericCommand(c, 1);
+}
43 tests/unit/type/zset.tcl
View
@@ -577,4 +577,47 @@ start_server {tags {"zset"}} {
r zincrby myzset +inf abc
assert_error "*NaN*" {r zincrby myzset -inf abc}
}
+
+ test {ZPOP/ZREVPOP basics} {
+ create_zset myzset {1 a 2 b 3 c}
+ assert_equal c [r zpop myzset]
+ assert_equal a [r zrevpop myzset]
+ assert_equal b [r zpop myzset]
+ assert_equal 0 [r zcard myzset]
+
+ # pop on empty
+ assert_equal {} [r zpop myzset]
+ assert_equal {} [r zrevpop myzset]
+ }
+
+ test {ZPOP with min/max score} {
+ create_zset myzset {1 a 2 b 3 c 4 d 5 e 6 f}
+ assert_equal f [r zpop myzset 5]
+ assert_equal e [r zpop myzset 5]
+ assert_equal {} [r zpop myzset 5]
+
+ assert_equal a [r zrevpop myzset 2]
+ assert_equal b [r zrevpop myzset 2]
+ assert_equal {} [r zrevpop myzset 2]
+ }
+
+ test {ZPOP/ZREVPOP against non zset value} {
+ r set notazset foo
+ assert_error ERR*kind* {r zpop notazset}
+ assert_error ERR*kind* {r zrevpop notazset}
+ }
+
+ test {ZPOP/REVPOP with non-double min/max score} {
+ create_default_zset
+ assert_error "*not a double*" {r zpop zset nan}
+ assert_error "*not a double*" {r zrevpop zset nan}
+ }
+
+ test {ZPOP/ZREVPOP with wrong number of args} {
+ create_default_zset
+ catch {r zpop zset 30 whatever} err
+ catch {r zrevpop zset 30 whatever} err
+ format $err
+ } {*syntax error*}
+
}
Please sign in to comment.
Something went wrong with that request. Please try again.