Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpredis/phpredis.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormichael-grunder <michael.grunder@gmail.com>2022-10-01 20:25:54 +0300
committerMichael Grunder <michael.grunder@gmail.com>2022-10-01 20:42:23 +0300
commit643005080839b35c40d78af40eda3e2743ad4d6f (patch)
tree51a2f7e4c3ad1fe09ef09119efb69d3075265eb8
parent239678a03bb9efcd30893a99c37ba62d22d22b5d (diff)
SINTERCARD and ZINTERCARD commands
Implement Redis 7.0.0 commands SINTERCARD and ZINTERCARD.
-rw-r--r--cluster_library.c4
-rw-r--r--cluster_library.h1
-rw-r--r--library.c41
-rw-r--r--library.h4
-rw-r--r--redis.c8
-rw-r--r--redis.stub.php4
-rw-r--r--redis_arginfo.h13
-rw-r--r--redis_cluster.c13
-rw-r--r--redis_cluster.stub.php4
-rw-r--r--redis_cluster_arginfo.h13
-rw-r--r--redis_cluster_legacy_arginfo.h13
-rw-r--r--redis_commands.c57
-rw-r--r--redis_commands.h4
-rw-r--r--redis_legacy_arginfo.h13
-rw-r--r--tests/RedisTest.php49
15 files changed, 237 insertions, 4 deletions
diff --git a/cluster_library.c b/cluster_library.c
index f11c2dcb..6e69c518 100644
--- a/cluster_library.c
+++ b/cluster_library.c
@@ -530,6 +530,10 @@ unsigned short cluster_hash_key(const char *key, int len) {
return crc16((char*)key+s+1,e-s-1) & REDIS_CLUSTER_MOD;
}
+unsigned short cluster_hash_key_zstr(zend_string *key) {
+ return cluster_hash_key(ZSTR_VAL(key), ZSTR_LEN(key));
+}
+
/* Grab the current time in milliseconds */
long long mstime(void) {
struct timeval tv;
diff --git a/cluster_library.h b/cluster_library.h
index fe2962f0..ddb29f29 100644
--- a/cluster_library.h
+++ b/cluster_library.h
@@ -352,6 +352,7 @@ void cluster_multi_fini(clusterMultiCmd *mc);
/* Hash a key to it's slot, using the Redis Cluster hash algorithm */
unsigned short cluster_hash_key_zval(zval *key);
unsigned short cluster_hash_key(const char *key, int len);
+unsigned short cluster_hash_key_zstr(zend_string *key);
/* Validate and sanitize cluster construction args */
zend_string** cluster_validate_args(double timeout, double read_timeout,
diff --git a/library.c b/library.c
index 647b73b3..67a49be0 100644
--- a/library.c
+++ b/library.c
@@ -3502,6 +3502,47 @@ redis_key_prefix(RedisSock *redis_sock, char **key, size_t *key_len) {
return 1;
}
+/* This is very similar to PHP >= 7.4 zend_string_concat2 only we are taking
+ * two zend_string arguments rather than two char*, size_t pairs */
+static zend_string *redis_zstr_concat(zend_string *prefix, zend_string *suffix) {
+ zend_string *res;
+ size_t len;
+
+ ZEND_ASSERT(prefix != NULL && suffix != NULL);
+
+ len = ZSTR_LEN(prefix) + ZSTR_LEN(suffix);
+ res = zend_string_alloc(len, 0);
+
+ memcpy(ZSTR_VAL(res), ZSTR_VAL(prefix), ZSTR_LEN(prefix));
+ memcpy(ZSTR_VAL(res) + ZSTR_LEN(prefix), ZSTR_VAL(suffix), ZSTR_LEN(suffix));
+ ZSTR_VAL(res)[len] = '\0';
+
+ return res;
+}
+
+PHP_REDIS_API zend_string *
+redis_key_prefix_zval(RedisSock *redis_sock, zval *zv) {
+ zend_string *zstr, *dup;
+
+ zstr = zval_get_string(zv);
+ if (redis_sock->prefix == NULL)
+ return zstr;
+
+ dup = redis_zstr_concat(redis_sock->prefix, zstr);
+
+ zend_string_release(zstr);
+
+ return dup;
+}
+
+PHP_REDIS_API zend_string *
+redis_key_prefix_zstr(RedisSock *redis_sock, zend_string *key) {
+ if (redis_sock->prefix == NULL)
+ return zend_string_copy(key);
+
+ return redis_zstr_concat(redis_sock->prefix, key);
+}
+
/*
* Processing for variant reply types (think EVAL)
*/
diff --git a/library.h b/library.h
index a632a84e..9e1cfd73 100644
--- a/library.h
+++ b/library.h
@@ -123,6 +123,10 @@ PHP_REDIS_API int
redis_serialize(RedisSock *redis_sock, zval *z, char **val, size_t *val_len);
PHP_REDIS_API int
redis_key_prefix(RedisSock *redis_sock, char **key, size_t *key_len);
+PHP_REDIS_API zend_string*
+redis_key_prefix_zval(RedisSock *redis_sock, zval *zv);
+PHP_REDIS_API zend_string *
+redis_key_prefix_zstr(RedisSock *redis_sock, zend_string *key);
PHP_REDIS_API int
redis_unserialize(RedisSock *redis_sock, const char *val, int val_len, zval *z_ret);
diff --git a/redis.c b/redis.c
index 017e60ee..ca8f96c5 100644
--- a/redis.c
+++ b/redis.c
@@ -1435,6 +1435,10 @@ PHP_METHOD(Redis, sInter) {
}
/* }}} */
+PHP_METHOD(Redis, sintercard) {
+ REDIS_PROCESS_KW_CMD("SINTERCARD", redis_intercard_cmd, redis_long_response);
+}
+
/* {{{ proto array Redis::sInterStore(string dst, string key0,...string keyN) */
PHP_METHOD(Redis, sInterStore) {
REDIS_PROCESS_CMD(sinterstore, redis_long_response);
@@ -2071,6 +2075,10 @@ PHP_METHOD(Redis, zinter) {
}
/* }}} */
+PHP_METHOD(Redis, zintercard) {
+ REDIS_PROCESS_KW_CMD("ZINTERCARD", redis_intercard_cmd, redis_long_response);
+}
+
/* {{{ proto array Redis::zunion(array keys, array|null weights, array options) */
PHP_METHOD(Redis, zunion) {
REDIS_PROCESS_KW_CMD("ZUNION", redis_zinterunion_cmd, redis_zdiff_response);
diff --git a/redis.stub.php b/redis.stub.php
index be56508d..7f125ddf 100644
--- a/redis.stub.php
+++ b/redis.stub.php
@@ -363,6 +363,8 @@ public function persist(string $key): bool;
public function sInter(string $key, string ...$other_keys): array;
+ public function sintercard(array $keys, int $limit = -1): Redis|int|false;
+
public function sInterStore(string $dst, string $key, string ...$other_keys): int;
public function sMembers(string $key): array;
@@ -548,6 +550,8 @@ public function persist(string $key): bool;
public function zinter(array $keys, array $weights = null, array $options = null): array;
+ public function zintercard(array $keys, int $limit = -1): Redis|int|false;
+
public function zinterstore(string $dst, array $keys, array $weights = null, string $aggregate = null): int;
public function zscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): bool|array;
diff --git a/redis_arginfo.h b/redis_arginfo.h
index 66176b34..33526de0 100644
--- a/redis_arginfo.h
+++ b/redis_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 122b5ca534302a09a4f072106d097f2831ba6f22 */
+ * Stub hash: f43a528bc5874c419161b5eb874537fbe9c00e87 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null")
@@ -628,6 +628,11 @@ ZEND_END_ARG_INFO()
#define arginfo_class_Redis_sInter arginfo_class_Redis_sDiff
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_sintercard, 0, 1, Redis, MAY_BE_LONG|MAY_BE_FALSE)
+ ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0)
+ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, limit, IS_LONG, 0, "-1")
+ZEND_END_ARG_INFO()
+
#define arginfo_class_Redis_sInterStore arginfo_class_Redis_sDiffStore
#define arginfo_class_Redis_sMembers arginfo_class_Redis_hGetAll
@@ -971,6 +976,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_zinter, 0, 1, IS_ARR
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null")
ZEND_END_ARG_INFO()
+#define arginfo_class_Redis_zintercard arginfo_class_Redis_sintercard
+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_zinterstore, 0, 2, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, dst, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0)
@@ -1130,6 +1137,7 @@ ZEND_METHOD(Redis, sAddArray);
ZEND_METHOD(Redis, sDiff);
ZEND_METHOD(Redis, sDiffStore);
ZEND_METHOD(Redis, sInter);
+ZEND_METHOD(Redis, sintercard);
ZEND_METHOD(Redis, sInterStore);
ZEND_METHOD(Redis, sMembers);
ZEND_METHOD(Redis, sMisMember);
@@ -1209,6 +1217,7 @@ ZEND_METHOD(Redis, zScore);
ZEND_METHOD(Redis, zdiff);
ZEND_METHOD(Redis, zdiffstore);
ZEND_METHOD(Redis, zinter);
+ZEND_METHOD(Redis, zintercard);
ZEND_METHOD(Redis, zinterstore);
ZEND_METHOD(Redis, zscan);
ZEND_METHOD(Redis, zunion);
@@ -1364,6 +1373,7 @@ static const zend_function_entry class_Redis_methods[] = {
ZEND_ME(Redis, sDiff, arginfo_class_Redis_sDiff, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, sDiffStore, arginfo_class_Redis_sDiffStore, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, sInter, arginfo_class_Redis_sInter, ZEND_ACC_PUBLIC)
+ ZEND_ME(Redis, sintercard, arginfo_class_Redis_sintercard, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, sInterStore, arginfo_class_Redis_sInterStore, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, sMembers, arginfo_class_Redis_sMembers, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, sMisMember, arginfo_class_Redis_sMisMember, ZEND_ACC_PUBLIC)
@@ -1443,6 +1453,7 @@ static const zend_function_entry class_Redis_methods[] = {
ZEND_ME(Redis, zdiff, arginfo_class_Redis_zdiff, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, zdiffstore, arginfo_class_Redis_zdiffstore, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, zinter, arginfo_class_Redis_zinter, ZEND_ACC_PUBLIC)
+ ZEND_ME(Redis, zintercard, arginfo_class_Redis_zintercard, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, zinterstore, arginfo_class_Redis_zinterstore, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, zscan, arginfo_class_Redis_zscan, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, zunion, arginfo_class_Redis_zunion, ZEND_ACC_PUBLIC)
diff --git a/redis_cluster.c b/redis_cluster.c
index f163158a..4be54bf8 100644
--- a/redis_cluster.c
+++ b/redis_cluster.c
@@ -1021,6 +1021,13 @@ PHP_METHOD(RedisCluster, sunionstore) {
PHP_METHOD(RedisCluster, sinter) {
CLUSTER_PROCESS_CMD(sinter, cluster_mbulk_resp, 0);
}
+
+/* {{{ proto RedisCluster::sintercard(array $keys, int $count = -1) */
+PHP_METHOD(RedisCluster, sintercard) {
+ CLUSTER_PROCESS_KW_CMD("SINTERCARD", redis_intercard_cmd, cluster_long_resp, 0);
+}
+/* }}} */
+
/* }}} */
/* {{{ ptoto long RedisCluster::sinterstore(string dst, string k1, ... kN) */
@@ -1457,6 +1464,12 @@ PHP_METHOD(RedisCluster, zinterstore) {
}
/* }}} */
+/* {{{ proto RedisCluster::zintercard(array $keys, int $count = -1) */
+PHP_METHOD(RedisCluster, zintercard) {
+ CLUSTER_PROCESS_KW_CMD("ZINTERCARD", redis_intercard_cmd, cluster_long_resp, 0);
+}
+/* }}} */
+
/* {{{ proto RedisCluster::zrem(string key, string val1, ... valN) */
PHP_METHOD(RedisCluster, zrem) {
CLUSTER_PROCESS_KW_CMD("ZREM", redis_key_varval_cmd, cluster_long_resp, 0);
diff --git a/redis_cluster.stub.php b/redis_cluster.stub.php
index ed0a8293..924b9c04 100644
--- a/redis_cluster.stub.php
+++ b/redis_cluster.stub.php
@@ -276,6 +276,8 @@ class RedisCluster {
public function sinter(string $key, string ...$other_keys): array;
+ public function sintercard(array $keys, int $limit = -1): Redis|int|false;
+
public function sinterstore(string $dst, string $key, string ...$other_keys): bool;
public function sismember(string $key): int;
@@ -354,6 +356,8 @@ class RedisCluster {
public function zinterstore(string $key, array $keys, array $weights = null, string $aggregate = null): int;
+ public function zintercard(array $keys, int $limit = -1): Redis|int|false;
+
public function zlexcount(string $key, string $min, string $max): int;
public function zpopmax(string $key, int $value = null): bool|array;
diff --git a/redis_cluster_arginfo.h b/redis_cluster_arginfo.h
index 842cd4a2..35f2ab11 100644
--- a/redis_cluster_arginfo.h
+++ b/redis_cluster_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 97fe79bf371074b77d22e1e820903fb2103d10c9 */
+ * Stub hash: c9bfd7de5c930c9d7190139e207eb6025e33bdb2 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 1)
@@ -584,6 +584,11 @@ ZEND_END_ARG_INFO()
#define arginfo_class_RedisCluster_sinter arginfo_class_RedisCluster_del
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_sintercard, 0, 1, Redis, MAY_BE_LONG|MAY_BE_FALSE)
+ ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0)
+ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, limit, IS_LONG, 0, "-1")
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_RedisCluster_sinterstore, 0, 2, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, dst, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
@@ -775,6 +780,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_RedisCluster_zinterstore,
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, aggregate, IS_STRING, 0, "null")
ZEND_END_ARG_INFO()
+#define arginfo_class_RedisCluster_zintercard arginfo_class_RedisCluster_sintercard
+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_RedisCluster_zlexcount, 0, 3, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, min, IS_STRING, 0)
@@ -973,6 +980,7 @@ ZEND_METHOD(RedisCluster, setnx);
ZEND_METHOD(RedisCluster, setoption);
ZEND_METHOD(RedisCluster, setrange);
ZEND_METHOD(RedisCluster, sinter);
+ZEND_METHOD(RedisCluster, sintercard);
ZEND_METHOD(RedisCluster, sinterstore);
ZEND_METHOD(RedisCluster, sismember);
ZEND_METHOD(RedisCluster, slowlog);
@@ -1012,6 +1020,7 @@ ZEND_METHOD(RedisCluster, zcard);
ZEND_METHOD(RedisCluster, zcount);
ZEND_METHOD(RedisCluster, zincrby);
ZEND_METHOD(RedisCluster, zinterstore);
+ZEND_METHOD(RedisCluster, zintercard);
ZEND_METHOD(RedisCluster, zlexcount);
ZEND_METHOD(RedisCluster, zpopmax);
ZEND_METHOD(RedisCluster, zpopmin);
@@ -1167,6 +1176,7 @@ static const zend_function_entry class_RedisCluster_methods[] = {
ZEND_ME(RedisCluster, setoption, arginfo_class_RedisCluster_setoption, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, setrange, arginfo_class_RedisCluster_setrange, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, sinter, arginfo_class_RedisCluster_sinter, ZEND_ACC_PUBLIC)
+ ZEND_ME(RedisCluster, sintercard, arginfo_class_RedisCluster_sintercard, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, sinterstore, arginfo_class_RedisCluster_sinterstore, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, sismember, arginfo_class_RedisCluster_sismember, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, slowlog, arginfo_class_RedisCluster_slowlog, ZEND_ACC_PUBLIC)
@@ -1206,6 +1216,7 @@ static const zend_function_entry class_RedisCluster_methods[] = {
ZEND_ME(RedisCluster, zcount, arginfo_class_RedisCluster_zcount, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, zincrby, arginfo_class_RedisCluster_zincrby, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, zinterstore, arginfo_class_RedisCluster_zinterstore, ZEND_ACC_PUBLIC)
+ ZEND_ME(RedisCluster, zintercard, arginfo_class_RedisCluster_zintercard, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, zlexcount, arginfo_class_RedisCluster_zlexcount, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, zpopmax, arginfo_class_RedisCluster_zpopmax, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, zpopmin, arginfo_class_RedisCluster_zpopmin, ZEND_ACC_PUBLIC)
diff --git a/redis_cluster_legacy_arginfo.h b/redis_cluster_legacy_arginfo.h
index 3cc0618d..bff23cd6 100644
--- a/redis_cluster_legacy_arginfo.h
+++ b/redis_cluster_legacy_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 97fe79bf371074b77d22e1e820903fb2103d10c9 */
+ * Stub hash: c9bfd7de5c930c9d7190139e207eb6025e33bdb2 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
ZEND_ARG_INFO(0, name)
@@ -507,6 +507,11 @@ ZEND_END_ARG_INFO()
#define arginfo_class_RedisCluster_sinter arginfo_class_RedisCluster_del
+ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_sintercard, 0, 0, 1)
+ ZEND_ARG_INFO(0, keys)
+ ZEND_ARG_INFO(0, limit)
+ZEND_END_ARG_INFO()
+
#define arginfo_class_RedisCluster_sinterstore arginfo_class_RedisCluster_sdiffstore
#define arginfo_class_RedisCluster_sismember arginfo_class_RedisCluster__prefix
@@ -673,6 +678,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_zinterstore, 0, 0, 2)
ZEND_ARG_INFO(0, aggregate)
ZEND_END_ARG_INFO()
+#define arginfo_class_RedisCluster_zintercard arginfo_class_RedisCluster_sintercard
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_zlexcount, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, min)
@@ -861,6 +868,7 @@ ZEND_METHOD(RedisCluster, setnx);
ZEND_METHOD(RedisCluster, setoption);
ZEND_METHOD(RedisCluster, setrange);
ZEND_METHOD(RedisCluster, sinter);
+ZEND_METHOD(RedisCluster, sintercard);
ZEND_METHOD(RedisCluster, sinterstore);
ZEND_METHOD(RedisCluster, sismember);
ZEND_METHOD(RedisCluster, slowlog);
@@ -900,6 +908,7 @@ ZEND_METHOD(RedisCluster, zcard);
ZEND_METHOD(RedisCluster, zcount);
ZEND_METHOD(RedisCluster, zincrby);
ZEND_METHOD(RedisCluster, zinterstore);
+ZEND_METHOD(RedisCluster, zintercard);
ZEND_METHOD(RedisCluster, zlexcount);
ZEND_METHOD(RedisCluster, zpopmax);
ZEND_METHOD(RedisCluster, zpopmin);
@@ -1055,6 +1064,7 @@ static const zend_function_entry class_RedisCluster_methods[] = {
ZEND_ME(RedisCluster, setoption, arginfo_class_RedisCluster_setoption, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, setrange, arginfo_class_RedisCluster_setrange, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, sinter, arginfo_class_RedisCluster_sinter, ZEND_ACC_PUBLIC)
+ ZEND_ME(RedisCluster, sintercard, arginfo_class_RedisCluster_sintercard, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, sinterstore, arginfo_class_RedisCluster_sinterstore, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, sismember, arginfo_class_RedisCluster_sismember, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, slowlog, arginfo_class_RedisCluster_slowlog, ZEND_ACC_PUBLIC)
@@ -1094,6 +1104,7 @@ static const zend_function_entry class_RedisCluster_methods[] = {
ZEND_ME(RedisCluster, zcount, arginfo_class_RedisCluster_zcount, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, zincrby, arginfo_class_RedisCluster_zincrby, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, zinterstore, arginfo_class_RedisCluster_zinterstore, ZEND_ACC_PUBLIC)
+ ZEND_ME(RedisCluster, zintercard, arginfo_class_RedisCluster_zintercard, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, zlexcount, arginfo_class_RedisCluster_zlexcount, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, zpopmax, arginfo_class_RedisCluster_zpopmax, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, zpopmin, arginfo_class_RedisCluster_zpopmin, ZEND_ACC_PUBLIC)
diff --git a/redis_commands.c b/redis_commands.c
index 3db45146..1db729a6 100644
--- a/redis_commands.c
+++ b/redis_commands.c
@@ -841,6 +841,63 @@ static int redis_cmd_append_sstr_score(smart_string *dst, zval *score) {
return FAILURE;
}
+int redis_intercard_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
+ char *kw, char **cmd, int *cmd_len, short *slot,
+ void **ctx)
+{
+ smart_string cmdstr = {0};
+ zend_long limit = -1;
+ HashTable *keys;
+ zend_string *key;
+ zval *zv;
+
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_ARRAY_HT(keys)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_LONG(limit)
+ ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
+
+ if (zend_hash_num_elements(keys) == 0) {
+ php_error_docref(NULL, E_WARNING, "Must pass at least one key");
+ return FAILURE;
+ } else if (ZEND_NUM_ARGS() == 2 && limit < 0) {
+ php_error_docref(NULL, E_WARNING, "LIMIT cannot be negative");
+ return FAILURE;
+ }
+
+ redis_cmd_init_sstr(&cmdstr, 1 + zend_hash_num_elements(keys) + (limit > 0 ? 2 : 0), kw, strlen(kw));
+ redis_cmd_append_sstr_long(&cmdstr, zend_hash_num_elements(keys));
+
+ if (slot) *slot = -1;
+
+ ZEND_HASH_FOREACH_VAL(keys, zv) {
+ key = redis_key_prefix_zval(redis_sock, zv);
+
+ if (slot) {
+ if (*slot == -1) {
+ *slot = cluster_hash_key_zstr(key);
+ } else if (*slot != cluster_hash_key_zstr(key)) {
+ php_error_docref(NULL, E_WARNING, "All keys don't hash to the same slot");
+ efree(cmdstr.c);
+ zend_string_release(key);
+ return FAILURE;
+ }
+ }
+
+ redis_cmd_append_sstr_zstr(&cmdstr, key);
+ zend_string_release(key);
+ } ZEND_HASH_FOREACH_END();
+
+ if (limit > 0) {
+ REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "LIMIT");
+ redis_cmd_append_sstr_long(&cmdstr, limit);
+ }
+
+ *cmd = cmdstr.c;
+ *cmd_len = cmdstr.len;
+ return SUCCESS;
+}
+
int
redis_zinterunion_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char *kw, char **cmd, int *cmd_len, short *slot,
diff --git a/redis_commands.h b/redis_commands.h
index 662d0500..24fbe92c 100644
--- a/redis_commands.h
+++ b/redis_commands.h
@@ -125,6 +125,10 @@ int redis_zdiffstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
int redis_zinterunionstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
+int redis_intercard_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
+ char *kw, char **cmd, int *cmd_len, short *slot,
+ void **ctx);
+
int redis_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
diff --git a/redis_legacy_arginfo.h b/redis_legacy_arginfo.h
index 1d7673e6..aaf02d19 100644
--- a/redis_legacy_arginfo.h
+++ b/redis_legacy_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 122b5ca534302a09a4f072106d097f2831ba6f22 */
+ * Stub hash: f43a528bc5874c419161b5eb874537fbe9c00e87 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
ZEND_ARG_INFO(0, options)
@@ -552,6 +552,11 @@ ZEND_END_ARG_INFO()
#define arginfo_class_Redis_sInter arginfo_class_Redis_del
+ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_sintercard, 0, 0, 1)
+ ZEND_ARG_INFO(0, keys)
+ ZEND_ARG_INFO(0, limit)
+ZEND_END_ARG_INFO()
+
#define arginfo_class_Redis_sInterStore arginfo_class_Redis_sDiffStore
#define arginfo_class_Redis_sMembers arginfo_class_Redis__prefix
@@ -863,6 +868,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_zinter, 0, 0, 1)
ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO()
+#define arginfo_class_Redis_zintercard arginfo_class_Redis_sintercard
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_zinterstore, 0, 0, 2)
ZEND_ARG_INFO(0, dst)
ZEND_ARG_INFO(0, keys)
@@ -1022,6 +1029,7 @@ ZEND_METHOD(Redis, sAddArray);
ZEND_METHOD(Redis, sDiff);
ZEND_METHOD(Redis, sDiffStore);
ZEND_METHOD(Redis, sInter);
+ZEND_METHOD(Redis, sintercard);
ZEND_METHOD(Redis, sInterStore);
ZEND_METHOD(Redis, sMembers);
ZEND_METHOD(Redis, sMisMember);
@@ -1101,6 +1109,7 @@ ZEND_METHOD(Redis, zScore);
ZEND_METHOD(Redis, zdiff);
ZEND_METHOD(Redis, zdiffstore);
ZEND_METHOD(Redis, zinter);
+ZEND_METHOD(Redis, zintercard);
ZEND_METHOD(Redis, zinterstore);
ZEND_METHOD(Redis, zscan);
ZEND_METHOD(Redis, zunion);
@@ -1256,6 +1265,7 @@ static const zend_function_entry class_Redis_methods[] = {
ZEND_ME(Redis, sDiff, arginfo_class_Redis_sDiff, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, sDiffStore, arginfo_class_Redis_sDiffStore, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, sInter, arginfo_class_Redis_sInter, ZEND_ACC_PUBLIC)
+ ZEND_ME(Redis, sintercard, arginfo_class_Redis_sintercard, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, sInterStore, arginfo_class_Redis_sInterStore, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, sMembers, arginfo_class_Redis_sMembers, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, sMisMember, arginfo_class_Redis_sMisMember, ZEND_ACC_PUBLIC)
@@ -1335,6 +1345,7 @@ static const zend_function_entry class_Redis_methods[] = {
ZEND_ME(Redis, zdiff, arginfo_class_Redis_zdiff, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, zdiffstore, arginfo_class_Redis_zdiffstore, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, zinter, arginfo_class_Redis_zinter, ZEND_ACC_PUBLIC)
+ ZEND_ME(Redis, zintercard, arginfo_class_Redis_zintercard, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, zinterstore, arginfo_class_Redis_zinterstore, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, zscan, arginfo_class_Redis_zscan, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, zunion, arginfo_class_Redis_zunion, ZEND_ACC_PUBLIC)
diff --git a/tests/RedisTest.php b/tests/RedisTest.php
index 6c04c9d0..551c6346 100644
--- a/tests/RedisTest.php
+++ b/tests/RedisTest.php
@@ -1948,6 +1948,55 @@ class Redis_Test extends TestSuite
$this->assertTrue($count === 0);
}
+ public function testInterCard() {
+ if(version_compare($this->version, "7.0.0") < 0) {
+ $this->markTestSkipped();
+ }
+
+ $set_data = [
+ ['aardvark', 'dog', 'fish', 'squirrel', 'tiger'],
+ ['bear', 'coyote', 'fish', 'gorilla', 'dog']
+ ];
+
+ $ssets = $zsets = [];
+
+ foreach ($set_data as $n => $values) {
+ $sset = "s{set}:$n";
+ $zset = "z{set}:$n";
+
+ $this->redis->del([$sset, $zset]);
+
+ $ssets[] = $sset;
+ $zsets[] = $zset;
+
+ foreach ($values as $score => $value) {
+ $this->assertEquals(1, $this->redis->sAdd("s{set}:$n", $value));
+ $this->assertEquals(1, $this->redis->zAdd("z{set}:$n", $score, $value));
+ }
+ }
+
+ $exp = count(array_intersect(...$set_data));
+
+ $act = $this->redis->sintercard($ssets);
+ $this->assertEquals($exp, $act);
+ $act = $this->redis->zintercard($zsets);
+ $this->assertEquals($exp, $act);
+
+ $this->assertEquals(1, $this->redis->sintercard($ssets, 1));
+ $this->assertEquals(2, $this->redis->sintercard($ssets, 2));
+
+ $this->assertEquals(1, $this->redis->zintercard($zsets, 1));
+ $this->assertEquals(2, $this->redis->zintercard($zsets, 2));
+
+ $this->assertFalse(@$this->redis->sintercard($ssets, -1));
+ $this->assertFalse(@$this->redis->zintercard($ssets, -1));
+
+ $this->assertFalse(@$this->redis->sintercard([]));
+ $this->assertFalse(@$this->redis->zintercard([]));
+
+ $this->redis->del(array_merge($ssets, $zsets));
+ }
+
public function testlrange() {
$this->redis->del('list');
$this->redis->lPush('list', 'val');