From e53ca04b50b86ef158a75c54ae9ee8b17e31719c Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Fri, 11 Mar 2011 18:17:53 +0100 Subject: [PATCH] Test for empty inner range when looking for elements in range --- src/t_zset.c | 32 ++++++++++++++++++++++---------- tests/unit/type/zset.tcl | 6 ++++++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/t_zset.c b/src/t_zset.c index 65c99622..b8a961eb 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -226,10 +226,12 @@ zskiplistNode *zslFirstInRange(zskiplist *zsl, zrangespec range) { x = x->level[i].forward; } - /* The tail is in range, so the previous block should always return a - * node that is non-NULL and the last one to be out of range. */ + /* This is an inner range, so the next node cannot be NULL. */ x = x->level[0].forward; - redisAssert(x != NULL && zslValueInRange(x->score,&range)); + redisAssert(x != NULL); + + /* Check if score <= max. */ + if (!zslValueLteMax(x->score,&range)) return NULL; return x; } @@ -250,9 +252,11 @@ zskiplistNode *zslLastInRange(zskiplist *zsl, zrangespec range) { x = x->level[i].forward; } - /* The header is in range, so the previous block should always return a - * node that is non-NULL and in range. */ - redisAssert(x != NULL && zslValueInRange(x->score,&range)); + /* This is an inner range, so this node cannot be NULL. */ + redisAssert(x != NULL); + + /* Check if score >= min. */ + if (!zslValueGteMin(x->score,&range)) return NULL; return x; } @@ -531,8 +535,12 @@ unsigned char *zzlFirstInRange(unsigned char *zl, zrangespec range) { redisAssert(sptr != NULL); score = zzlGetScore(sptr); - if (zslValueGteMin(score,&range)) - return eptr; + if (zslValueGteMin(score,&range)) { + /* Check if score <= max. */ + if (zslValueLteMax(score,&range)) + return eptr; + return NULL; + } /* Move to next element. */ eptr = ziplistNext(zl,sptr); @@ -555,8 +563,12 @@ unsigned char *zzlLastInRange(unsigned char *zl, zrangespec range) { redisAssert(sptr != NULL); score = zzlGetScore(sptr); - if (zslValueLteMax(score,&range)) - return eptr; + if (zslValueLteMax(score,&range)) { + /* Check if score >= min. */ + if (zslValueGteMin(score,&range)) + return eptr; + return NULL; + } /* Move to previous element by moving to the score of previous element. * When this returns NULL, we know there also is no element. */ diff --git a/tests/unit/type/zset.tcl b/tests/unit/type/zset.tcl index fdeebd2f..6218a95c 100644 --- a/tests/unit/type/zset.tcl +++ b/tests/unit/type/zset.tcl @@ -247,6 +247,12 @@ start_server {tags {"zset"}} { assert_equal {} [r zrangebyscore zset (-inf (-6] assert_equal {} [r zrevrangebyscore zset (+inf (6] assert_equal {} [r zrevrangebyscore zset (-6 (-inf] + + # empty inner range + assert_equal {} [r zrangebyscore zset 2.4 2.6] + assert_equal {} [r zrangebyscore zset (2.4 2.6] + assert_equal {} [r zrangebyscore zset 2.4 (2.6] + assert_equal {} [r zrangebyscore zset (2.4 (2.6] } test "ZRANGEBYSCORE with WITHSCORES" {