/* Retrieve value from hash by the field name. This operation
* already increases the refcount of the returned object. */
initStaticStringObject(fieldobj,((char*)&fieldname)+(sizeof(struct sdshdr)));
- o = hashTypeGet(o, &fieldobj);
+ o = hashTypeGetObject(o, &fieldobj);
} else {
if (o->type != REDIS_STRING) return NULL;
j++;
}
+ /* Destructively convert encoded sorted sets for SORT. */
+ if (sortval->type == REDIS_ZSET) zsetConvert(sortval, REDIS_ENCODING_SKIPLIST);
+
/* Load the sorting vector with all the objects to sort */
switch(sortval->type) {
case REDIS_LIST: vectorlen = listTypeLength(sortval); break;
- case REDIS_SET: vectorlen = dictSize((dict*)sortval->ptr); break;
+ case REDIS_SET: vectorlen = setTypeSize(sortval); break;
case REDIS_ZSET: vectorlen = dictSize(((zset*)sortval->ptr)->dict); break;
default: vectorlen = 0; redisPanic("Bad SORT type"); /* Avoid GCC warning */
}
j++;
}
listTypeReleaseIterator(li);
- } else {
- dict *set;
+ } else if (sortval->type == REDIS_SET) {
+ setTypeIterator *si = setTypeInitIterator(sortval);
+ robj *ele;
+ while((ele = setTypeNextObject(si)) != NULL) {
+ vector[j].obj = ele;
+ vector[j].u.score = 0;
+ vector[j].u.cmpobj = NULL;
+ j++;
+ }
+ setTypeReleaseIterator(si);
+ } else if (sortval->type == REDIS_ZSET) {
+ dict *set = ((zset*)sortval->ptr)->dict;
dictIterator *di;
dictEntry *setele;
-
- if (sortval->type == REDIS_SET) {
- set = sortval->ptr;
- } else {
- zset *zs = sortval->ptr;
- set = zs->dict;
- }
-
di = dictGetIterator(set);
while((setele = dictNext(di)) != NULL) {
vector[j].obj = dictGetEntryKey(setele);
j++;
}
dictReleaseIterator(di);
+ } else {
+ redisPanic("Unknown type");
}
- redisAssert(j == vectorlen);
+ redisAssertWithInfo(c,sortval,j == vectorlen);
/* Now it's time to load the right scores in the sorting vector */
if (dontsort == 0) {
* far. We can just cast it */
vector[j].u.score = (long)byval->ptr;
} else {
- redisAssert(1 != 1);
+ redisAssertWithInfo(c,sortval,1 != 1);
}
}
outputlen = getop ? getop*(end-start+1) : end-start+1;
if (storekey == NULL) {
/* STORE option not specified, sent the sorting result to client */
- addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",outputlen));
+ addReplyMultiBulkLen(c,outputlen);
for (j = start; j <= end; j++) {
listNode *ln;
listIter li;
decrRefCount(val);
}
} else {
- redisAssert(sop->type == REDIS_SORT_GET); /* always fails */
+ /* Always fails */
+ redisAssertWithInfo(c,sortval,sop->type == REDIS_SORT_GET);
}
}
}
listTypePush(sobj,val,REDIS_TAIL);
decrRefCount(val);
} else {
- /* always fails */
- redisAssert(sop->type == REDIS_SORT_GET);
+ /* Always fails */
+ redisAssertWithInfo(c,sortval,sop->type == REDIS_SORT_GET);
}
}
}
}
- dbReplace(c->db,storekey,sobj);
+ setKey(c->db,storekey,sobj);
+ decrRefCount(sobj);
/* Note: we add 1 because the DB is dirty anyway since even if the
* SORT result is empty a new key is set and maybe the old content
* replaced. */
server.dirty += 1+outputlen;
- touchWatchedKey(c->db,storekey);
- addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",outputlen));
+ addReplyLongLong(c,outputlen);
}
/* Cleanup */
- if (sortval->type == REDIS_LIST)
+ if (sortval->type == REDIS_LIST || sortval->type == REDIS_SET)
for (j = 0; j < vectorlen; j++)
decrRefCount(vector[j].obj);
decrRefCount(sortval);