@@ -444,6 +444,7 @@ static void msetCommand(redisClient *c);
444
444
static void msetnxCommand (redisClient * c );
445
445
static void zaddCommand (redisClient * c );
446
446
static void zrangeCommand (redisClient * c );
447
+ static void zrangebyscoreCommand (redisClient * c );
447
448
static void zrevrangeCommand (redisClient * c );
448
449
static void zlenCommand (redisClient * c );
449
450
static void zremCommand (redisClient * c );
@@ -488,6 +489,7 @@ static struct redisCommand cmdTable[] = {
488
489
{"zadd" ,zaddCommand ,4 ,REDIS_CMD_BULK |REDIS_CMD_DENYOOM },
489
490
{"zrem" ,zremCommand ,3 ,REDIS_CMD_BULK },
490
491
{"zrange" ,zrangeCommand ,4 ,REDIS_CMD_INLINE },
492
+ {"zrangebyscore" ,zrangebyscoreCommand ,4 ,REDIS_CMD_INLINE },
491
493
{"zrevrange" ,zrevrangeCommand ,4 ,REDIS_CMD_INLINE },
492
494
{"zlen" ,zlenCommand ,2 ,REDIS_CMD_INLINE },
493
495
{"incrby" ,incrbyCommand ,3 ,REDIS_CMD_INLINE |REDIS_CMD_DENYOOM },
@@ -3885,6 +3887,7 @@ static void zslInsert(zskiplist *zsl, double score, robj *obj) {
3885
3887
zsl -> length ++ ;
3886
3888
}
3887
3889
3890
+ /* Delete an element with matching score/object from the skiplist. */
3888
3891
static int zslDelete (zskiplist * zsl , double score , robj * obj ) {
3889
3892
zskiplistNode * update [ZSKIPLIST_MAXLEVEL ], * x ;
3890
3893
int i ;
@@ -3901,7 +3904,7 @@ static int zslDelete(zskiplist *zsl, double score, robj *obj) {
3901
3904
/* We may have multiple elements with the same score, what we need
3902
3905
* is to find the element with both the right score and object. */
3903
3906
x = x -> forward [0 ];
3904
- if (compareStringObjects (x -> obj ,obj ) == 0 ) {
3907
+ if (x && score == x -> score && compareStringObjects (x -> obj ,obj ) == 0 ) {
3905
3908
for (i = 0 ; i < zsl -> level ; i ++ ) {
3906
3909
if (update [i ]-> forward [i ] != x ) break ;
3907
3910
update [i ]-> forward [i ] = x -> forward [i ];
@@ -3923,6 +3926,22 @@ static int zslDelete(zskiplist *zsl, double score, robj *obj) {
3923
3926
return 0 ; /* not found */
3924
3927
}
3925
3928
3929
+ /* Find the first node having a score equal or greater than the specified one.
3930
+ * Returns NULL if there is no match. */
3931
+ static zskiplistNode * zslFirstWithScore (zskiplist * zsl , double score ) {
3932
+ zskiplistNode * x ;
3933
+ int i ;
3934
+
3935
+ x = zsl -> header ;
3936
+ for (i = zsl -> level - 1 ; i >= 0 ; i -- ) {
3937
+ while (x -> forward [i ] && x -> forward [i ]-> score < score )
3938
+ x = x -> forward [i ];
3939
+ }
3940
+ /* We may have multiple elements with the same score, what we need
3941
+ * is to find the element with both the right score and object. */
3942
+ return x -> forward [0 ];
3943
+ }
3944
+
3926
3945
/* The actual Z-commands implementations */
3927
3946
3928
3947
static void zaddCommand (redisClient * c ) {
@@ -4076,6 +4095,52 @@ static void zrevrangeCommand(redisClient *c) {
4076
4095
zrangeGenericCommand (c ,1 );
4077
4096
}
4078
4097
4098
+ static void zrangebyscoreCommand (redisClient * c ) {
4099
+ robj * o ;
4100
+ double min = strtod (c -> argv [2 ]-> ptr ,NULL );
4101
+ double max = strtod (c -> argv [3 ]-> ptr ,NULL );
4102
+
4103
+ o = lookupKeyRead (c -> db ,c -> argv [1 ]);
4104
+ if (o == NULL ) {
4105
+ addReply (c ,shared .nullmultibulk );
4106
+ } else {
4107
+ if (o -> type != REDIS_ZSET ) {
4108
+ addReply (c ,shared .wrongtypeerr );
4109
+ } else {
4110
+ zset * zsetobj = o -> ptr ;
4111
+ zskiplist * zsl = zsetobj -> zsl ;
4112
+ zskiplistNode * ln ;
4113
+ robj * ele , * lenobj ;
4114
+ unsigned int rangelen = 0 ;
4115
+
4116
+ /* Get the first node with the score >= min */
4117
+ ln = zslFirstWithScore (zsl ,min );
4118
+ if (ln == NULL ) {
4119
+ /* No element matching the speciifed interval */
4120
+ addReply (c ,shared .emptymultibulk );
4121
+ return ;
4122
+ }
4123
+
4124
+ /* We don't know in advance how many matching elements there
4125
+ * are in the list, so we push this object that will represent
4126
+ * the multi-bulk length in the output buffer, and will "fix"
4127
+ * it later */
4128
+ lenobj = createObject (REDIS_STRING ,NULL );
4129
+ addReply (c ,lenobj );
4130
+
4131
+ while (ln -> score <= max ) {
4132
+ ele = ln -> obj ;
4133
+ addReplyBulkLen (c ,ele );
4134
+ addReply (c ,ele );
4135
+ addReply (c ,shared .crlf );
4136
+ ln = ln -> forward [0 ];
4137
+ rangelen ++ ;
4138
+ }
4139
+ lenobj -> ptr = sdscatprintf (sdsempty (),"*%d\r\n" ,rangelen );
4140
+ }
4141
+ }
4142
+ }
4143
+
4079
4144
static void zlenCommand (redisClient * c ) {
4080
4145
robj * o ;
4081
4146
zset * zs ;
0 commit comments