summaryrefslogtreecommitdiff
path: root/src/t_set.c
diff options
context:
space:
mode:
authorJonah H. Harris <jonah.harris@gmail.com>2021-08-03 04:45:27 -0400
committerGitHub <noreply@github.com>2021-08-03 11:45:27 +0300
commit432c92d8df179a6a1aeae2df553c6b3fc810be76 (patch)
tree7fb64e93ee532ebe6f508c68f8f108b68a6606dd /src/t_set.c
parentbdbf5eedae55a1eea869cc5a31832d0c35113c66 (diff)
downloadredis-432c92d8df179a6a1aeae2df553c6b3fc810be76.tar.gz
Add SINTERCARD/ZINTERCARD Commands (#8946)
Add SINTERCARD and ZINTERCARD commands that are similar to ZINTER and SINTER but only return the cardinality with minimum processing and memory overheads. Co-authored-by: Oran Agra <oran@redislabs.com>
Diffstat (limited to 'src/t_set.c')
-rw-r--r--src/t_set.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/src/t_set.c b/src/t_set.c
index 88c5c7994..57a29a98f 100644
--- a/src/t_set.c
+++ b/src/t_set.c
@@ -850,7 +850,7 @@ int qsortCompareSetsByRevCardinality(const void *s1, const void *s2) {
}
void sinterGenericCommand(client *c, robj **setkeys,
- unsigned long setnum, robj *dstkey) {
+ unsigned long setnum, robj *dstkey, int cardinality_only) {
robj **sets = zmalloc(sizeof(robj*)*setnum);
setTypeIterator *si;
robj *dstset = NULL;
@@ -888,6 +888,8 @@ void sinterGenericCommand(client *c, robj **setkeys,
server.dirty++;
}
addReply(c,shared.czero);
+ } else if (cardinality_only) {
+ addReplyLongLong(c,cardinality);
} else {
addReply(c,shared.emptyset[c->resp]);
}
@@ -903,12 +905,12 @@ void sinterGenericCommand(client *c, robj **setkeys,
* the intersection set size, so we use a trick, append an empty object
* to the output list and save the pointer to later modify it with the
* right length */
- if (!dstkey) {
- replylen = addReplyDeferredLen(c);
- } else {
+ if (dstkey) {
/* If we have a target key where to store the resulting set
* create this key with an empty set inside */
dstset = createIntsetObject();
+ } else if (!cardinality_only) {
+ replylen = addReplyDeferredLen(c);
}
/* Iterate all the elements of the first (smallest) set, and test
@@ -944,7 +946,9 @@ void sinterGenericCommand(client *c, robj **setkeys,
/* Only take action when all sets contain the member */
if (j == setnum) {
- if (!dstkey) {
+ if (cardinality_only) {
+ cardinality++;
+ } else if (!dstkey) {
if (encoding == OBJ_ENCODING_HT)
addReplyBulkCBuffer(c,elesds,sdslen(elesds));
else
@@ -963,7 +967,9 @@ void sinterGenericCommand(client *c, robj **setkeys,
}
setTypeReleaseIterator(si);
- if (dstkey) {
+ if (cardinality_only) {
+ addReplyLongLong(c,cardinality);
+ } else if (dstkey) {
/* Store the resulting set into the target, if the intersection
* is not an empty set. */
if (setTypeSize(dstset) > 0) {
@@ -989,12 +995,16 @@ void sinterGenericCommand(client *c, robj **setkeys,
/* SINTER key [key ...] */
void sinterCommand(client *c) {
- sinterGenericCommand(c,c->argv+1,c->argc-1,NULL);
+ sinterGenericCommand(c,c->argv+1,c->argc-1,NULL,0);
+}
+
+void sinterCardCommand(client *c) {
+ sinterGenericCommand(c,c->argv+1,c->argc-1,NULL,1);
}
/* SINTERSTORE destination key [key ...] */
void sinterstoreCommand(client *c) {
- sinterGenericCommand(c,c->argv+2,c->argc-2,c->argv[1]);
+ sinterGenericCommand(c,c->argv+2,c->argc-2,c->argv[1],0);
}
#define SET_OP_UNION 0