mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-23 08:38:27 -05:00
enable hash dereference in SORT on BY and GET
This commit is contained in:
parent
6e9e463f80
commit
6d7d1370c3
91
redis.c
91
redis.c
@ -6470,16 +6470,16 @@ static redisSortOperation *createSortOperation(int type, robj *pattern) {
|
|||||||
/* Return the value associated to the key with a name obtained
|
/* Return the value associated to the key with a name obtained
|
||||||
* substituting the first occurence of '*' in 'pattern' with 'subst' */
|
* substituting the first occurence of '*' in 'pattern' with 'subst' */
|
||||||
static robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst) {
|
static robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst) {
|
||||||
char *p;
|
char *p, *f;
|
||||||
sds spat, ssub;
|
sds spat, ssub;
|
||||||
robj keyobj;
|
robj keyobj, fieldobj, *o;
|
||||||
int prefixlen, sublen, postfixlen;
|
int prefixlen, sublen, postfixlen, fieldlen;
|
||||||
/* Expoit the internal sds representation to create a sds string allocated on the stack in order to make this function faster */
|
/* Expoit the internal sds representation to create a sds string allocated on the stack in order to make this function faster */
|
||||||
struct {
|
struct {
|
||||||
long len;
|
long len;
|
||||||
long free;
|
long free;
|
||||||
char buf[REDIS_SORTKEY_MAX+1];
|
char buf[REDIS_SORTKEY_MAX+1];
|
||||||
} keyname;
|
} keyname, fieldname;
|
||||||
|
|
||||||
/* If the pattern is "#" return the substitution object itself in order
|
/* If the pattern is "#" return the substitution object itself in order
|
||||||
* to implement the "SORT ... GET #" feature. */
|
* to implement the "SORT ... GET #" feature. */
|
||||||
@ -6501,20 +6501,40 @@ static robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find out if we're dealing with a hash dereference. */
|
||||||
|
if ((f = strstr(p+1, "->")) != NULL) {
|
||||||
|
fieldlen = sdslen(spat)-(f-spat);
|
||||||
|
/* this also copies \0 character */
|
||||||
|
memcpy(fieldname.buf,f+2,fieldlen-1);
|
||||||
|
fieldname.len = fieldlen-2;
|
||||||
|
} else {
|
||||||
|
fieldlen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
prefixlen = p-spat;
|
prefixlen = p-spat;
|
||||||
sublen = sdslen(ssub);
|
sublen = sdslen(ssub);
|
||||||
postfixlen = sdslen(spat)-(prefixlen+1);
|
postfixlen = sdslen(spat)-(prefixlen+1)-fieldlen;
|
||||||
memcpy(keyname.buf,spat,prefixlen);
|
memcpy(keyname.buf,spat,prefixlen);
|
||||||
memcpy(keyname.buf+prefixlen,ssub,sublen);
|
memcpy(keyname.buf+prefixlen,ssub,sublen);
|
||||||
memcpy(keyname.buf+prefixlen+sublen,p+1,postfixlen);
|
memcpy(keyname.buf+prefixlen+sublen,p+1,postfixlen);
|
||||||
keyname.buf[prefixlen+sublen+postfixlen] = '\0';
|
keyname.buf[prefixlen+sublen+postfixlen] = '\0';
|
||||||
keyname.len = prefixlen+sublen+postfixlen;
|
keyname.len = prefixlen+sublen+postfixlen;
|
||||||
|
|
||||||
initStaticStringObject(keyobj,((char*)&keyname)+(sizeof(long)*2))
|
|
||||||
decrRefCount(subst);
|
decrRefCount(subst);
|
||||||
|
|
||||||
/* printf("lookup '%s' => %p\n", keyname.buf,de); */
|
/* Lookup substituted key */
|
||||||
return lookupKeyRead(db,&keyobj);
|
initStaticStringObject(keyobj,((char*)&keyname)+(sizeof(long)*2));
|
||||||
|
o = lookupKeyRead(db,&keyobj);
|
||||||
|
|
||||||
|
/* Retrieve value from hash by the field name */
|
||||||
|
if (o != NULL && fieldlen > 0) {
|
||||||
|
if (o->type != REDIS_HASH || fieldname.len < 1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
initStaticStringObject(fieldobj,((char*)&fieldname)+(sizeof(long)*2));
|
||||||
|
o = hashGet(o, &fieldobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sortCompare() is used by qsort in sortCommand(). Given that qsort_r with
|
/* sortCompare() is used by qsort in sortCommand(). Given that qsort_r with
|
||||||
@ -6683,36 +6703,37 @@ static void sortCommand(redisClient *c) {
|
|||||||
/* Now it's time to load the right scores in the sorting vector */
|
/* Now it's time to load the right scores in the sorting vector */
|
||||||
if (dontsort == 0) {
|
if (dontsort == 0) {
|
||||||
for (j = 0; j < vectorlen; j++) {
|
for (j = 0; j < vectorlen; j++) {
|
||||||
|
robj *byval;
|
||||||
if (sortby) {
|
if (sortby) {
|
||||||
robj *byval;
|
/* lookup value to sort by */
|
||||||
|
|
||||||
byval = lookupKeyByPattern(c->db,sortby,vector[j].obj);
|
byval = lookupKeyByPattern(c->db,sortby,vector[j].obj);
|
||||||
if (!byval || byval->type != REDIS_STRING) continue;
|
if (!byval || byval->type != REDIS_STRING) continue;
|
||||||
if (alpha) {
|
|
||||||
vector[j].u.cmpobj = getDecodedObject(byval);
|
|
||||||
} else {
|
|
||||||
if (byval->encoding == REDIS_ENCODING_RAW) {
|
|
||||||
vector[j].u.score = strtod(byval->ptr,NULL);
|
|
||||||
} else {
|
|
||||||
/* Don't need to decode the object if it's
|
|
||||||
* integer-encoded (the only encoding supported) so
|
|
||||||
* far. We can just cast it */
|
|
||||||
if (byval->encoding == REDIS_ENCODING_INT) {
|
|
||||||
vector[j].u.score = (long)byval->ptr;
|
|
||||||
} else
|
|
||||||
redisAssert(1 != 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!alpha) {
|
/* use object itself to sort by */
|
||||||
if (vector[j].obj->encoding == REDIS_ENCODING_RAW)
|
byval = vector[j].obj;
|
||||||
vector[j].u.score = strtod(vector[j].obj->ptr,NULL);
|
}
|
||||||
else {
|
|
||||||
if (vector[j].obj->encoding == REDIS_ENCODING_INT)
|
if (alpha) {
|
||||||
vector[j].u.score = (long) vector[j].obj->ptr;
|
/* getDecodedObject increments refcount, so the corresponding
|
||||||
else
|
* decrRefCount will clean up values coming from a zipmap. */
|
||||||
redisAssert(1 != 1);
|
vector[j].u.cmpobj = getDecodedObject(byval);
|
||||||
}
|
} else {
|
||||||
|
if (byval->encoding == REDIS_ENCODING_RAW) {
|
||||||
|
vector[j].u.score = strtod(byval->ptr,NULL);
|
||||||
|
} else {
|
||||||
|
/* Don't need to decode the object if it's
|
||||||
|
* integer-encoded (the only encoding supported) so
|
||||||
|
* far. We can just cast it */
|
||||||
|
if (byval->encoding == REDIS_ENCODING_INT) {
|
||||||
|
vector[j].u.score = (long)byval->ptr;
|
||||||
|
} else
|
||||||
|
redisAssert(1 != 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clean up immediately if this value came from a zipmap */
|
||||||
|
if (byval->refcount == 0) {
|
||||||
|
byval->refcount = 1;
|
||||||
|
decrRefCount(byval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user