summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Semprebon <eduardobr@gmail.com>2021-08-09 08:40:29 +0200
committerGitHub <noreply@github.com>2021-08-09 09:40:29 +0300
commitd3356bf614155f2a4352a0630065d715ce073b8a (patch)
tree8bdad343594943673ca7336e784a000c54df7569
parente8eeba7bee6add5286afc4d59db074a924fb9209 (diff)
downloadredis-d3356bf614155f2a4352a0630065d715ce073b8a.tar.gz
Add SORT_RO command (#9299)
Add a readonly variant of the STORE command, so it can be used on read-only workloads (replica, ACL, etc)
-rw-r--r--src/server.c4
-rw-r--r--src/server.h1
-rw-r--r--src/sort.c13
-rw-r--r--tests/unit/sort.tcl12
4 files changed, 28 insertions, 2 deletions
diff --git a/src/server.c b/src/server.c
index 0ae43d148..756fa5be8 100644
--- a/src/server.c
+++ b/src/server.c
@@ -789,6 +789,10 @@ struct redisCommand redisCommandTable[] = {
"write use-memory @list @set @sortedset @dangerous",
0,sortGetKeys,1,1,1,0,0,0},
+ {"sort_ro",sortroCommand,-2,
+ "read-only @list @set @sortedset @dangerous",
+ 0,NULL,1,1,1,0,0,0},
+
{"info",infoCommand,-1,
"ok-loading ok-stale random @dangerous",
0,NULL,0,0,0,0,0,0},
diff --git a/src/server.h b/src/server.h
index e45558f8e..4f797d592 100644
--- a/src/server.h
+++ b/src/server.h
@@ -2606,6 +2606,7 @@ void syncCommand(client *c);
void flushdbCommand(client *c);
void flushallCommand(client *c);
void sortCommand(client *c);
+void sortroCommand(client *c);
void lremCommand(client *c);
void lposCommand(client *c);
void rpoplpushCommand(client *c);
diff --git a/src/sort.c b/src/sort.c
index 53f9ef0cb..1eb61f83a 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -189,7 +189,7 @@ int sortCompare(const void *s1, const void *s2) {
/* The SORT command is the most complex command in Redis. Warning: this code
* is optimized for speed and a bit less for readability */
-void sortCommand(client *c) {
+void sortCommandGeneric(client *c, int readonly) {
list *operations;
unsigned int outputlen = 0;
int desc = 0, alpha = 0;
@@ -226,7 +226,7 @@ void sortCommand(client *c) {
break;
}
j+=2;
- } else if (!strcasecmp(c->argv[j]->ptr,"store") && leftargs >= 1) {
+ } else if (readonly == 0 && !strcasecmp(c->argv[j]->ptr,"store") && leftargs >= 1) {
storekey = c->argv[j+1];
j++;
} else if (!strcasecmp(c->argv[j]->ptr,"by") && leftargs >= 1) {
@@ -595,3 +595,12 @@ void sortCommand(client *c) {
}
zfree(vector);
}
+
+/* SORT wrapper function for read-only mode. */
+void sortroCommand(client *c) {
+ sortCommandGeneric(c, 1);
+}
+
+void sortCommand(client *c) {
+ sortCommandGeneric(c, 0);
+}
diff --git a/tests/unit/sort.tcl b/tests/unit/sort.tcl
index a892c3a48..a9264eadf 100644
--- a/tests/unit/sort.tcl
+++ b/tests/unit/sort.tcl
@@ -263,6 +263,18 @@ start_server {
r lrange testb 0 -1
} {5 3 4} {cluster:skip}
+ test "SORT_RO - Successful case" {
+ r del mylist
+ r lpush mylist a
+ r set x:a 100
+ r sort_ro mylist by nosort get x:*->
+ } {100} {cluster:skip}
+
+ test "SORT_RO - Cannot run with STORE arg" {
+ catch {r sort_ro foolist STORE bar} e
+ set e
+ } {ERR syntax error}
+
tags {"slow"} {
set num 100
set res [create_random_dataset $num lpush]