summaryrefslogtreecommitdiff
path: root/src/t_zset.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/t_zset.c')
-rw-r--r--src/t_zset.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/src/t_zset.c b/src/t_zset.c
index 4b28c24ef..2ef02ac8a 100644
--- a/src/t_zset.c
+++ b/src/t_zset.c
@@ -1283,6 +1283,10 @@ int zsetScore(robj *zobj, sds member, double *score) {
* assume 0 as previous score.
* ZADD_NX: Perform the operation only if the element does not exist.
* ZADD_XX: Perform the operation only if the element already exist.
+ * ZADD_GT: Perform the operation on existing elements only if the new score is
+ * greater than the current score.
+ * ZADD_LT: Perform the operation on existing elements only if the new score is
+ * less than the current score.
*
* When ZADD_INCR is used, the new score of the element is stored in
* '*newscore' if 'newscore' is not NULL.
@@ -1317,6 +1321,8 @@ int zsetAdd(robj *zobj, double score, sds ele, int *flags, double *newscore) {
int incr = (*flags & ZADD_INCR) != 0;
int nx = (*flags & ZADD_NX) != 0;
int xx = (*flags & ZADD_XX) != 0;
+ int gt = (*flags & ZADD_GT) != 0;
+ int lt = (*flags & ZADD_LT) != 0;
*flags = 0; /* We'll return our response flags. */
double curscore;
@@ -1348,7 +1354,12 @@ int zsetAdd(robj *zobj, double score, sds ele, int *flags, double *newscore) {
}
/* Remove and re-insert when score changed. */
- if (score != curscore) {
+ if (score != curscore &&
+ /* LT? Only update if score is less than current. */
+ (!lt || score < curscore) &&
+ /* GT? Only update if score is greater than current. */
+ (!gt || score > curscore))
+ {
zobj->ptr = zzlDelete(zobj->ptr,eptr);
zobj->ptr = zzlInsert(zobj->ptr,ele,score);
*flags |= ZADD_UPDATED;
@@ -1393,7 +1404,12 @@ int zsetAdd(robj *zobj, double score, sds ele, int *flags, double *newscore) {
}
/* Remove and re-insert when score changes. */
- if (score != curscore) {
+ if (score != curscore &&
+ /* LT? Only update if score is less than current. */
+ (!lt || score < curscore) &&
+ /* GT? Only update if score is greater than current. */
+ (!gt || score > curscore))
+ {
znode = zslUpdateScore(zs->zsl,curscore,ele,score);
/* Note that we did not removed the original element from
* the hash table representing the sorted set, so we just
@@ -1555,6 +1571,8 @@ void zaddGenericCommand(client *c, int flags) {
else if (!strcasecmp(opt,"xx")) flags |= ZADD_XX;
else if (!strcasecmp(opt,"ch")) flags |= ZADD_CH;
else if (!strcasecmp(opt,"incr")) flags |= ZADD_INCR;
+ else if (!strcasecmp(opt,"gt")) flags |= ZADD_GT;
+ else if (!strcasecmp(opt,"lt")) flags |= ZADD_LT;
else break;
scoreidx++;
}
@@ -1564,6 +1582,8 @@ void zaddGenericCommand(client *c, int flags) {
int nx = (flags & ZADD_NX) != 0;
int xx = (flags & ZADD_XX) != 0;
int ch = (flags & ZADD_CH) != 0;
+ int gt = (flags & ZADD_GT) != 0;
+ int lt = (flags & ZADD_LT) != 0;
/* After the options, we expect to have an even number of args, since
* we expect any number of score-element pairs. */
@@ -1580,6 +1600,13 @@ void zaddGenericCommand(client *c, int flags) {
"XX and NX options at the same time are not compatible");
return;
}
+
+ if ((gt && nx) || (lt && nx) || (gt && lt)) {
+ addReplyError(c,
+ "GT, LT, and/or NX options at the same time are not compatible");
+ return;
+ }
+ /* Note that XX is compatible with either GT or LT */
if (incr && elements > 1) {
addReplyError(c,