diff --git a/src/db.c b/src/db.c index 94a85e9d0..8bb6df67d 100644 --- a/src/db.c +++ b/src/db.c @@ -1028,6 +1028,51 @@ int *evalGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) return keys; } +/* Helper function to extract keys from the SORT command. + * + * SORT ... STORE ... + * + * The first argument of SORT is always a key, however a list of options + * follow in SQL-alike style. Here we parse just the minimum in order to + * correctly identify keys in the "STORE" option. */ +int *sortGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) { + int i, j, num, *keys; + REDIS_NOTUSED(cmd); + + num = 0; + keys = zmalloc(sizeof(int)*2); /* Alloc 2 places for the worst case. */ + + keys[num++] = 1; /* is always present. */ + + /* Search for STORE option. By default we consider options to don't + * have arguments, so if we find an unknown option name we scan the + * next. However there are options with 1 or 2 arguments, so we + * provide a list here in order to skip the right number of args. */ + struct { + char *name; + int skip; + } skiplist[] = { + {"limit", 2}, + {"get", 1}, + {"by", 1}, + {NULL, 0} /* End of elements. */ + }; + + for (i = 2; i < argc; i++) { + for (j = 0; skiplist[j].name != NULL; j++) { + if (!strcasecmp(argv[i]->ptr,skiplist[j].name)) { + i += skiplist[j].skip; + break; + } else if (!strcasecmp(argv[i]->ptr,"store") && i+1 < argc) { + keys[num++] = i+1; /* */ + break; + } + } + } + *numkeys = num; + return keys; +} + /* Slot to Key API. This is used by Redis Cluster in order to obtain in * a fast way a key that belongs to a specified hash slot. This is useful * while rehashing the cluster. */ diff --git a/src/redis.c b/src/redis.c index 2c0e28070..23bf013e3 100644 --- a/src/redis.c +++ b/src/redis.c @@ -232,7 +232,7 @@ struct redisCommand redisCommandTable[] = { {"replconf",replconfCommand,-1,"arslt",0,NULL,0,0,0,0,0}, {"flushdb",flushdbCommand,1,"w",0,NULL,0,0,0,0,0}, {"flushall",flushallCommand,1,"w",0,NULL,0,0,0,0,0}, - {"sort",sortCommand,-2,"wm",0,NULL,1,1,1,0,0}, + {"sort",sortCommand,-2,"wm",0,sortGetKeys,1,1,1,0,0}, {"info",infoCommand,-1,"rlt",0,NULL,0,0,0,0,0}, {"monitor",monitorCommand,1,"ars",0,NULL,0,0,0,0,0}, {"ttl",ttlCommand,2,"r",0,NULL,1,1,1,0,0}, diff --git a/src/redis.h b/src/redis.h index 03ff7c84a..e92db52b7 100644 --- a/src/redis.h +++ b/src/redis.h @@ -1241,6 +1241,7 @@ int *getKeysFromCommand(struct redisCommand *cmd, robj **argv, int argc, int *nu void getKeysFreeResult(int *result); int *zunionInterGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys); int *evalGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys); +int *sortGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys); /* Cluster */ void clusterInit(void);