zset *zs;
double *score;
- if (isnan(scoreval)) {
- addReplySds(c,sdsnew("-ERR provide score is Not A Number (nan)\r\n"));
- return;
- }
-
zsetobj = lookupKeyWrite(c->db,key);
if (zsetobj == NULL) {
zsetobj = createZsetObject();
}
if (isnan(*score)) {
addReplySds(c,
- sdsnew("-ERR resulting score is Not A Number (nan)\r\n"));
+ sdsnew("-ERR resulting score is not a number (NaN)\r\n"));
zfree(score);
/* Note that we don't need to check if the zset may be empty and
* should be removed here, as we can only obtain Nan as score if
incrRefCount(ele); /* added to hash */
zslInsert(zs->zsl,*score,ele);
incrRefCount(ele); /* added to skiplist */
+ touchWatchedKey(c->db,c->argv[1]);
server.dirty++;
if (doincrement)
addReplyDouble(c,*score);
incrRefCount(ele);
/* Update the score in the hash table */
dictReplace(zs->dict,ele,score);
+ touchWatchedKey(c->db,c->argv[1]);
server.dirty++;
} else {
zfree(score);
void zaddCommand(redisClient *c) {
double scoreval;
-
- if (getDoubleFromObjectOrReply(c, c->argv[2], &scoreval, NULL) != REDIS_OK) return;
+ if (getDoubleFromObjectOrReply(c,c->argv[2],&scoreval,NULL) != REDIS_OK) return;
zaddGenericCommand(c,c->argv[1],c->argv[3],scoreval,0);
}
void zincrbyCommand(redisClient *c) {
double scoreval;
-
- if (getDoubleFromObjectOrReply(c, c->argv[2], &scoreval, NULL) != REDIS_OK) return;
+ if (getDoubleFromObjectOrReply(c,c->argv[2],&scoreval,NULL) != REDIS_OK) return;
zaddGenericCommand(c,c->argv[1],c->argv[3],scoreval,1);
}
dictDelete(zs->dict,c->argv[2]);
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++;
addReply(c,shared.cone);
}
deleted = zslDeleteRangeByScore(zs->zsl,min,max,zs->dict);
if (htNeedsResize(zs->dict)) dictResize(zs->dict);
if (dictSize(zs->dict) == 0) dbDelete(c->db,c->argv[1]);
+ if (deleted) touchWatchedKey(c->db,c->argv[1]);
server.dirty += deleted;
addReplyLongLong(c,deleted);
}
if (start < 0) start = llen+start;
if (end < 0) end = llen+end;
if (start < 0) start = 0;
- if (end < 0) end = 0;
- /* indexes sanity checks */
+ /* Invariant: start >= 0, so this test will be true when end < 0.
+ * The range is empty when start > end or start >= length. */
if (start > end || start >= llen) {
addReply(c,shared.czero);
return;
deleted = zslDeleteRangeByRank(zs->zsl,start+1,end+1,zs->dict);
if (htNeedsResize(zs->dict)) dictResize(zs->dict);
if (dictSize(zs->dict) == 0) dbDelete(c->db,c->argv[1]);
+ if (deleted) touchWatchedKey(c->db,c->argv[1]);
server.dirty += deleted;
addReplyLongLong(c, deleted);
}
inline static void zunionInterAggregate(double *target, double val, int aggregate) {
if (aggregate == REDIS_AGGR_SUM) {
*target = *target + val;
+ /* The result of adding two doubles is NaN when one variable
+ * is +inf and the other is -inf. When these numbers are added,
+ * we maintain the convention of the result being 0.0. */
+ if (isnan(*target)) *target = 0.0;
} else if (aggregate == REDIS_AGGR_MIN) {
*target = val < *target ? val : *target;
} else if (aggregate == REDIS_AGGR_MAX) {
zset *dstzset;
dictIterator *di;
dictEntry *de;
+ int touched = 0;
/* expect setnum input keys to be given */
setnum = atoi(c->argv[2]->ptr);
if (remaining >= (setnum + 1) && !strcasecmp(c->argv[j]->ptr,"weights")) {
j++; remaining--;
for (i = 0; i < setnum; i++, j++, remaining--) {
- if (getDoubleFromObjectOrReply(c, c->argv[j], &src[i].weight, NULL) != REDIS_OK)
+ if (getDoubleFromObjectOrReply(c,c->argv[j],&src[i].weight,
+ "weight value is not a double") != REDIS_OK)
+ {
+ zfree(src);
return;
+ }
}
} else if (remaining >= 2 && !strcasecmp(c->argv[j]->ptr,"aggregate")) {
j++; remaining--;
redisAssert(op == REDIS_OP_INTER || op == REDIS_OP_UNION);
}
- dbDelete(c->db,dstkey);
+ if (dbDelete(c->db,dstkey)) {
+ touchWatchedKey(c->db,dstkey);
+ touched = 1;
+ server.dirty++;
+ }
if (dstzset->zsl->length) {
dbAdd(c->db,dstkey,dstobj);
addReplyLongLong(c, dstzset->zsl->length);
+ if (!touched) touchWatchedKey(c->db,dstkey);
server.dirty++;
} else {
decrRefCount(dstobj);
if (start < 0) start = llen+start;
if (end < 0) end = llen+end;
if (start < 0) start = 0;
- if (end < 0) end = 0;
- /* indexes sanity checks */
+ /* Invariant: start >= 0, so this test will be true when end < 0.
+ * The range is empty when start > end or start >= length. */
if (start > end || start >= llen) {
- /* Out of range start or start > end result in empty list */
addReply(c,shared.emptymultibulk);
return;
}