summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/db.c45
-rw-r--r--src/redis.c2
-rw-r--r--src/redis.h1
3 files changed, 47 insertions, 1 deletions
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 <sort-key> ... STORE <store-key> ...
+ *
+ * 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; /* <sort-key> 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; /* <store-key> */
+ 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);