Support by/get options for sort(_ro) in cluster mode when pattern implies slot. (#12728)

The by/get options of sort/sort_ro command used to be forbidden in
cluster mode, since we are not sure which slot the pattern may be in.

As the optimization done in #12536, patterns now can be mapped to slots,
we should allow by/get options in cluster mode when the pattern maps to
the same slot as the key.
This commit is contained in:
Chen Tianjie 2023-12-14 03:16:36 +08:00 committed by GitHub
parent 3c0fd25201
commit e95a5d4831
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 6 deletions

View File

@ -32,6 +32,7 @@
#include "server.h"
#include "pqsort.h" /* Partial qsort for SORT+LIMIT */
#include <math.h> /* isnan() */
#include "cluster.h"
zskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank);
@ -235,10 +236,12 @@ void sortCommandGeneric(client *c, int readonly) {
if (strchr(c->argv[j+1]->ptr,'*') == NULL) {
dontsort = 1;
} else {
/* If BY is specified with a real pattern, we can't accept
* it in cluster mode. */
if (server.cluster_enabled) {
addReplyError(c,"BY option of SORT denied in Cluster mode.");
/* If BY is specified with a real pattern, we can't accept it in cluster mode,
* unless we can make sure the keys formed by the pattern are in the same slot
* as the key to sort. */
if (server.cluster_enabled && patternHashSlot(sortby->ptr, sdslen(sortby->ptr)) != c->slot) {
addReplyError(c, "BY option of SORT denied in Cluster mode when "
"keys formed by the pattern may be in different slots.");
syntax_error++;
break;
}
@ -252,8 +255,12 @@ void sortCommandGeneric(client *c, int readonly) {
}
j++;
} else if (!strcasecmp(c->argv[j]->ptr,"get") && leftargs >= 1) {
if (server.cluster_enabled) {
addReplyError(c,"GET option of SORT denied in Cluster mode.");
/* If GET is specified with a real pattern, we can't accept it in cluster mode,
* unless we can make sure the keys formed by the pattern are in the same slot
* as the key to sort. */
if (server.cluster_enabled && patternHashSlot(c->argv[j+1]->ptr, sdslen(c->argv[j+1]->ptr)) != c->slot) {
addReplyError(c, "GET option of SORT denied in Cluster mode when "
"keys formed by the pattern may be in different slots.");
syntax_error++;
break;
}

View File

@ -357,3 +357,39 @@ foreach command {SORT SORT_RO} {
}
}
}
start_cluster 1 0 {tags {"external:skip cluster sort"}} {
r flushall
r lpush "{a}mylist" 1 2 3
r set "{a}by1" 20
r set "{a}by2" 30
r set "{a}by3" 0
r set "{a}get1" 200
r set "{a}get2" 100
r set "{a}get3" 30
test "sort by in cluster mode" {
catch {r sort "{a}mylist" by by*} e
assert_match {ERR BY option of SORT denied in Cluster mode when *} $e
r sort "{a}mylist" by "{a}by*"
} {3 1 2}
test "sort get in cluster mode" {
catch {r sort "{a}mylist" by "{a}by*" get get*} e
assert_match {ERR GET option of SORT denied in Cluster mode when *} $e
r sort "{a}mylist" by "{a}by*" get "{a}get*"
} {30 200 100}
test "sort_ro by in cluster mode" {
catch {r sort_ro "{a}mylist" by by*} e
assert_match {ERR BY option of SORT denied in Cluster mode when *} $e
r sort_ro "{a}mylist" by "{a}by*"
} {3 1 2}
test "sort_ro get in cluster mode" {
catch {r sort_ro "{a}mylist" by "{a}by*" get get*} e
assert_match {ERR GET option of SORT denied in Cluster mode when *} $e
r sort_ro "{a}mylist" by "{a}by*" get "{a}get*"
} {30 200 100}
}