Implement several hash expiration commands

Commands implemented:

`H[P]EXPIRE`
`H[P]TTL`
`H[P]EXPIREAT`
`H[P]EXPIRETIME`
`HPERSIST`
This commit is contained in:
michael-grunder
2025-05-06 10:37:21 -07:00
committed by Michael Grunder
parent 593ba012ac
commit 7350768cd9
12 changed files with 622 additions and 6 deletions

View File

@@ -2027,7 +2027,7 @@ redis_hello_response(INTERNAL_FUNCTION_PARAMETERS,
array_init(&z_ret);
if (redis_read_multibulk_recursive(redis_sock, numElems, 0, &z_ret) != SUCCESS ||
array_zip_values_recursive(&z_ret) != SUCCESS)
array_zip_values_recursive(&z_ret) != SUCCESS)
{
zval_dtor(&z_ret);
goto fail;

45
redis.c
View File

@@ -1878,6 +1878,51 @@ PHP_METHOD(Redis, hMset)
}
/* }}} */
PHP_METHOD(Redis, hexpire) {
REDIS_PROCESS_KW_CMD("HEXPIRE", redis_hexpire_cmd,
redis_read_variant_reply);
}
PHP_METHOD(Redis, hpexpire) {
REDIS_PROCESS_KW_CMD("HPEXPIRE", redis_hexpire_cmd,
redis_read_variant_reply);
}
PHP_METHOD(Redis, hexpireat) {
REDIS_PROCESS_KW_CMD("HEXPIREAT", redis_hexpire_cmd,
redis_read_variant_reply);
}
PHP_METHOD(Redis, hpexpireat) {
REDIS_PROCESS_KW_CMD("HPEXPIREAT", redis_hexpire_cmd,
redis_read_variant_reply);
}
PHP_METHOD(Redis, httl) {
REDIS_PROCESS_KW_CMD("HTTL", redis_httl_cmd,
redis_read_variant_reply);
}
PHP_METHOD(Redis, hpttl) {
REDIS_PROCESS_KW_CMD("HPTTL", redis_httl_cmd,
redis_read_variant_reply);
}
PHP_METHOD(Redis, hexpiretime) {
REDIS_PROCESS_KW_CMD("HEXPIRETIME", redis_httl_cmd,
redis_read_variant_reply);
}
PHP_METHOD(Redis, hpexpiretime) {
REDIS_PROCESS_KW_CMD("HPEXPIRETIME", redis_httl_cmd,
redis_read_variant_reply);
}
PHP_METHOD(Redis, hpersist) {
REDIS_PROCESS_KW_CMD("HPERSIST", redis_httl_cmd,
redis_read_variant_reply);
}
/* {{{ proto bool Redis::hRandField(string key, [array $options]) */
PHP_METHOD(Redis, hRandField)
{

View File

@@ -1913,6 +1913,121 @@ class Redis {
*/
public function hVals(string $key): Redis|array|false;
/**
* Set the expiration on one or more fields in a hash.
*
* @param string $key The hash to update.
* @param int $ttl The time to live in seconds.
* @param array $fields The fields to set the expiration on.
* @param string|null $option An optional mode (NX, XX, ETC)
* @return Redis|array|false
*
* @see https://redis.io/commands/hexpire
*/
public function hexpire(string $key, int $ttl, array $fields,
?string $mode = NULL): Redis|array|false;
/**
* Set the expiration on one or more fields in a hash in milliseconds.
*
* @param string $key The hash to update.
* @param int $ttl The time to live in milliseconds.
* @param array $fields The fields to set the expiration on.
* @param string|null $option An optional mode (NX, XX, ETC)
* @return Redis|array|false
*
* @see https://redis.io/commands/hexpire
*/
public function hpexpire(string $key, int $ttl, array $fields,
?string $mode = NULL): Redis|array|false;
/**
* Set the expiration time on one or more fields of a hash.
*
* @param string $key The hash to update.
* @param int $time The time to live in seconds.
* @param array $fields The fields to set the expiration on.
* @param string|null $option An optional mode (NX, XX, ETC)
* @return Redis|array|false
*
* @see https://redis.io/commands/hexpire
*/
public function hexpireat(string $key, int $time, array $fields,
?string $mode = NULL): Redis|array|false;
/**
* Set the expiration time on one or more fields of a hash in milliseconds.
*
* @param string $key The hash to update.
* @param int $mstime The time to live in milliseconds.
* @param array $fields The fields to set the expiration on.
* @param string|null $option An optional mode (NX, XX, ETC)
* @return Redis|array|false
*
* @see https://redis.io/commands/hexpire
*/
public function hpexpireat(string $key, int $mstime, array $fields,
?string $mode = NULL): Redis|array|false;
/**
* Get the TTL of one or more fields in a hash
*
* @param string $key The hash to query.
* @param array $fields The fields to query.
*
* @return Redis|array|false
*
* @see https://redis.io/commands/httl
*/
public function httl(string $key, array $fields): Redis|array|false;
/**
* Get the millisecond TTL of one or more fields in a hash
*
* @param string $key The hash to query.
* @param array $fields The fields to query.
*
* @return Redis|array|false
*
* @see https://redis.io/commands/hpttl
*/
public function hpttl(string $key, array $fields): Redis|array|false;
/**
* Get the expiration time of one or more fields in a hash
*
* @param string $key The hash to query.
* @param array $fields The fields to query.
*
* @return Redis|array|false
*
* @see https://redis.io/commands/hexpiretime
*/
public function hexpiretime(string $key, array $fields): Redis|array|false;
/**
* Get the expiration time in milliseconds of one or more fields in a hash
*
* @param string $key The hash to query.
* @param array $fields The fields to query.
*
* @return Redis|array|false
*
* @see https://redis.io/commands/hpexpiretime
*/
public function hpexpiretime(string $key, array $fields): Redis|array|false;
/**
* Persist one or more hash fields
*
* @param string $key The hash to query.
* @param array $fields The fields to query.
*
* @return Redis|array|false
*
* @see https://redis.io/commands/hpersist
*/
public function hpersist(string $key, array $fields): Redis|array|false;
/**
* Iterate over the fields and values of a hash in an incremental fashion.

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 3a08bc16dd5a73e721e0df8f7843acdbbb585df5 */
* Stub hash: c6205649cd23ff2b9fcc63a034b601ee566ef236 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null")
@@ -464,6 +464,39 @@ ZEND_END_ARG_INFO()
#define arginfo_class_Redis_hVals arginfo_class_Redis_getWithMeta
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hexpire, 0, 3, Redis, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, ttl, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, fields, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_STRING, 1, "NULL")
ZEND_END_ARG_INFO()
#define arginfo_class_Redis_hpexpire arginfo_class_Redis_hexpire
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hexpireat, 0, 3, Redis, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, time, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, fields, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_STRING, 1, "NULL")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hpexpireat, 0, 3, Redis, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, mstime, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, fields, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_STRING, 1, "NULL")
ZEND_END_ARG_INFO()
#define arginfo_class_Redis_httl arginfo_class_Redis_hMget
#define arginfo_class_Redis_hpttl arginfo_class_Redis_hMget
#define arginfo_class_Redis_hexpiretime arginfo_class_Redis_hMget
#define arginfo_class_Redis_hpexpiretime arginfo_class_Redis_hMget
#define arginfo_class_Redis_hpersist arginfo_class_Redis_hMget
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hscan, 0, 2, Redis, MAY_BE_ARRAY|MAY_BE_BOOL)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_MASK(1, iterator, MAY_BE_NULL|MAY_BE_LONG|MAY_BE_STRING, NULL)
@@ -1292,6 +1325,15 @@ ZEND_METHOD(Redis, hSet);
ZEND_METHOD(Redis, hSetNx);
ZEND_METHOD(Redis, hStrLen);
ZEND_METHOD(Redis, hVals);
ZEND_METHOD(Redis, hexpire);
ZEND_METHOD(Redis, hpexpire);
ZEND_METHOD(Redis, hexpireat);
ZEND_METHOD(Redis, hpexpireat);
ZEND_METHOD(Redis, httl);
ZEND_METHOD(Redis, hpttl);
ZEND_METHOD(Redis, hexpiretime);
ZEND_METHOD(Redis, hpexpiretime);
ZEND_METHOD(Redis, hpersist);
ZEND_METHOD(Redis, hscan);
ZEND_METHOD(Redis, expiremember);
ZEND_METHOD(Redis, expirememberat);
@@ -1553,6 +1595,15 @@ static const zend_function_entry class_Redis_methods[] = {
ZEND_ME(Redis, hSetNx, arginfo_class_Redis_hSetNx, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hStrLen, arginfo_class_Redis_hStrLen, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hVals, arginfo_class_Redis_hVals, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hexpire, arginfo_class_Redis_hexpire, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hpexpire, arginfo_class_Redis_hpexpire, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hexpireat, arginfo_class_Redis_hexpireat, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hpexpireat, arginfo_class_Redis_hpexpireat, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, httl, arginfo_class_Redis_httl, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hpttl, arginfo_class_Redis_hpttl, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hexpiretime, arginfo_class_Redis_hexpiretime, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hpexpiretime, arginfo_class_Redis_hpexpiretime, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hpersist, arginfo_class_Redis_hpersist, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hscan, arginfo_class_Redis_hscan, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, expiremember, arginfo_class_Redis_expiremember, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, expirememberat, arginfo_class_Redis_expirememberat, ZEND_ACC_PUBLIC)

View File

@@ -1203,6 +1203,49 @@ PHP_METHOD(RedisCluster, hmset) {
}
/* }}} */
PHP_METHOD(RedisCluster, hexpire) {
CLUSTER_PROCESS_KW_CMD("HEXPIRE",
redis_hexpire_cmd, cluster_variant_resp, 0);
}
PHP_METHOD(RedisCluster, hpexpire) {
CLUSTER_PROCESS_KW_CMD("HPEXPIRE",
redis_hexpire_cmd, cluster_variant_resp, 0);
}
PHP_METHOD(RedisCluster, hexpireat) {
CLUSTER_PROCESS_KW_CMD("HEXPIREAT",
redis_hexpire_cmd, cluster_variant_resp, 0);
}
PHP_METHOD(RedisCluster, hpexpireat) {
CLUSTER_PROCESS_KW_CMD("HPEXPIREAT",
redis_hexpire_cmd, cluster_variant_resp, 0);
}
PHP_METHOD(RedisCluster, httl) {
CLUSTER_PROCESS_KW_CMD("HTTL", redis_httl_cmd, cluster_variant_resp, 1);
}
PHP_METHOD(RedisCluster, hpttl) {
CLUSTER_PROCESS_KW_CMD("HPTTL", redis_httl_cmd, cluster_variant_resp, 1);
}
PHP_METHOD(RedisCluster, hexpiretime) {
CLUSTER_PROCESS_KW_CMD("HEXPIRETIME", redis_httl_cmd,
cluster_variant_resp, 1);
}
PHP_METHOD(RedisCluster, hpexpiretime) {
CLUSTER_PROCESS_KW_CMD("HPEXPIRETIME", redis_httl_cmd,
cluster_variant_resp, 1);
}
PHP_METHOD(RedisCluster, hpersist) {
CLUSTER_PROCESS_KW_CMD("HPERSIST", redis_httl_cmd, cluster_variant_resp, 0);
}
/* {{{ proto bool RedisCluster::hrandfield(string key, [array $options]) */
PHP_METHOD(RedisCluster, hrandfield) {
CLUSTER_PROCESS_CMD(hrandfield, cluster_hrandfield_resp, 1);

View File

@@ -535,6 +535,55 @@ class RedisCluster {
*/
public function hstrlen(string $key, string $field): RedisCluster|int|false;
/**
* @see Redis::hexpire
*/
public function hexpire(string $key, int $ttl, array $fields,
?string $mode = NULL): RedisCluster|array|false;
/**
* @see Redis::hpexpire
*/
public function hpexpire(string $key, int $ttl, array $fields,
?string $mode = NULL): RedisCluster|array|false;
/**
* @see Redis::hexpireat
*/
public function hexpireat(string $key, int $time, array $fields,
?string $mode = NULL): RedisCluster|array|false;
/**
* @see Redis::hpexpireat
*/
public function hpexpireat(string $key, int $mstime, array $fields,
?string $mode = NULL): RedisCluster|array|false;
/**
* @see Redis::httl
*/
public function httl(string $key, array $fields): RedisCluster|array|false;
/**
* @see Redis::hpttl
*/
public function hpttl(string $key, array $fields): RedisCluster|array|false;
/**
* @see Redis::hexpiretime
*/
public function hexpiretime(string $key, array $fields): RedisCluster|array|false;
/**
* @see Redis::hpexpiretime
*/
public function hpexpiretime(string $key, array $fields): RedisCluster|array|false;
/**
* @see Redis::hpexpiretime
*/
public function hpersist(string $key, array $fields): RedisCluster|array|false;
/**
* @see Redis::hvals
*/

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 43a43fa735ced4b48a361078ac8a10fb62cb1244 */
* Stub hash: 5788cd1d12611ef1ff5747efe07b99f66f07fa05 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 1)
@@ -455,6 +455,42 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_hstrlen,
ZEND_ARG_TYPE_INFO(0, field, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_hexpire, 0, 3, RedisCluster, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, ttl, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, fields, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_STRING, 1, "NULL")
ZEND_END_ARG_INFO()
#define arginfo_class_RedisCluster_hpexpire arginfo_class_RedisCluster_hexpire
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_hexpireat, 0, 3, RedisCluster, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, time, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, fields, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_STRING, 1, "NULL")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_hpexpireat, 0, 3, RedisCluster, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, mstime, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, fields, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_STRING, 1, "NULL")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_httl, 0, 2, RedisCluster, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, fields, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_RedisCluster_hpttl arginfo_class_RedisCluster_httl
#define arginfo_class_RedisCluster_hexpiretime arginfo_class_RedisCluster_httl
#define arginfo_class_RedisCluster_hpexpiretime arginfo_class_RedisCluster_httl
#define arginfo_class_RedisCluster_hpersist arginfo_class_RedisCluster_httl
#define arginfo_class_RedisCluster_hvals arginfo_class_RedisCluster_getWithMeta
#define arginfo_class_RedisCluster_incr arginfo_class_RedisCluster_decr
@@ -1160,6 +1196,15 @@ ZEND_METHOD(RedisCluster, hrandfield);
ZEND_METHOD(RedisCluster, hset);
ZEND_METHOD(RedisCluster, hsetnx);
ZEND_METHOD(RedisCluster, hstrlen);
ZEND_METHOD(RedisCluster, hexpire);
ZEND_METHOD(RedisCluster, hpexpire);
ZEND_METHOD(RedisCluster, hexpireat);
ZEND_METHOD(RedisCluster, hpexpireat);
ZEND_METHOD(RedisCluster, httl);
ZEND_METHOD(RedisCluster, hpttl);
ZEND_METHOD(RedisCluster, hexpiretime);
ZEND_METHOD(RedisCluster, hpexpiretime);
ZEND_METHOD(RedisCluster, hpersist);
ZEND_METHOD(RedisCluster, hvals);
ZEND_METHOD(RedisCluster, incr);
ZEND_METHOD(RedisCluster, incrby);
@@ -1391,6 +1436,15 @@ static const zend_function_entry class_RedisCluster_methods[] = {
ZEND_ME(RedisCluster, hset, arginfo_class_RedisCluster_hset, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hsetnx, arginfo_class_RedisCluster_hsetnx, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hstrlen, arginfo_class_RedisCluster_hstrlen, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hexpire, arginfo_class_RedisCluster_hexpire, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hpexpire, arginfo_class_RedisCluster_hpexpire, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hexpireat, arginfo_class_RedisCluster_hexpireat, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hpexpireat, arginfo_class_RedisCluster_hpexpireat, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, httl, arginfo_class_RedisCluster_httl, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hpttl, arginfo_class_RedisCluster_hpttl, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hexpiretime, arginfo_class_RedisCluster_hexpiretime, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hpexpiretime, arginfo_class_RedisCluster_hpexpiretime, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hpersist, arginfo_class_RedisCluster_hpersist, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hvals, arginfo_class_RedisCluster_hvals, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, incr, arginfo_class_RedisCluster_incr, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, incrby, arginfo_class_RedisCluster_incrby, ZEND_ACC_PUBLIC)

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 43a43fa735ced4b48a361078ac8a10fb62cb1244 */
* Stub hash: 5788cd1d12611ef1ff5747efe07b99f66f07fa05 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
ZEND_ARG_INFO(0, name)
@@ -396,6 +396,42 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_hstrlen, 0, 0, 2)
ZEND_ARG_INFO(0, field)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_hexpire, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, ttl)
ZEND_ARG_INFO(0, fields)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
#define arginfo_class_RedisCluster_hpexpire arginfo_class_RedisCluster_hexpire
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_hexpireat, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, time)
ZEND_ARG_INFO(0, fields)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_hpexpireat, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, mstime)
ZEND_ARG_INFO(0, fields)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_httl, 0, 0, 2)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, fields)
ZEND_END_ARG_INFO()
#define arginfo_class_RedisCluster_hpttl arginfo_class_RedisCluster_httl
#define arginfo_class_RedisCluster_hexpiretime arginfo_class_RedisCluster_httl
#define arginfo_class_RedisCluster_hpexpiretime arginfo_class_RedisCluster_httl
#define arginfo_class_RedisCluster_hpersist arginfo_class_RedisCluster_httl
#define arginfo_class_RedisCluster_hvals arginfo_class_RedisCluster__prefix
#define arginfo_class_RedisCluster_incr arginfo_class_RedisCluster_decr
@@ -1002,6 +1038,15 @@ ZEND_METHOD(RedisCluster, hrandfield);
ZEND_METHOD(RedisCluster, hset);
ZEND_METHOD(RedisCluster, hsetnx);
ZEND_METHOD(RedisCluster, hstrlen);
ZEND_METHOD(RedisCluster, hexpire);
ZEND_METHOD(RedisCluster, hpexpire);
ZEND_METHOD(RedisCluster, hexpireat);
ZEND_METHOD(RedisCluster, hpexpireat);
ZEND_METHOD(RedisCluster, httl);
ZEND_METHOD(RedisCluster, hpttl);
ZEND_METHOD(RedisCluster, hexpiretime);
ZEND_METHOD(RedisCluster, hpexpiretime);
ZEND_METHOD(RedisCluster, hpersist);
ZEND_METHOD(RedisCluster, hvals);
ZEND_METHOD(RedisCluster, incr);
ZEND_METHOD(RedisCluster, incrby);
@@ -1233,6 +1278,15 @@ static const zend_function_entry class_RedisCluster_methods[] = {
ZEND_ME(RedisCluster, hset, arginfo_class_RedisCluster_hset, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hsetnx, arginfo_class_RedisCluster_hsetnx, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hstrlen, arginfo_class_RedisCluster_hstrlen, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hexpire, arginfo_class_RedisCluster_hexpire, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hpexpire, arginfo_class_RedisCluster_hpexpire, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hexpireat, arginfo_class_RedisCluster_hexpireat, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hpexpireat, arginfo_class_RedisCluster_hpexpireat, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, httl, arginfo_class_RedisCluster_httl, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hpttl, arginfo_class_RedisCluster_hpttl, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hexpiretime, arginfo_class_RedisCluster_hexpiretime, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hpexpiretime, arginfo_class_RedisCluster_hpexpiretime, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hpersist, arginfo_class_RedisCluster_hpersist, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hvals, arginfo_class_RedisCluster_hvals, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, incr, arginfo_class_RedisCluster_incr, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, incrby, arginfo_class_RedisCluster_incrby, ZEND_ACC_PUBLIC)

View File

@@ -2375,7 +2375,7 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
}
/* Calculate argc based on options set */
int argc = 2 + (ifeq ? 2 : 0) + (exp_type ? 2 : 0) + (set_type != NULL) +
int argc = 2 + (ifeq ? 2 : 0) + (exp_type ? 2 : 0) + (set_type != NULL) +
(keep_ttl != 0) + get;
/* Initial SET <key> <value> */
@@ -4634,6 +4634,92 @@ redis_geosearchstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
Starting with Redis version 6.0.0: Added the AUTH2 option.
*/
int redis_httl_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw,
char **cmd, int *cmd_len, short *slot, void **ctx)
{
smart_string cmdstr = {0};
zend_string *key, *field, *tmp;
HashTable *fields;
int argc;
zval *zv;
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_STR(key)
Z_PARAM_ARRAY_HT(fields)
ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
if (zend_hash_num_elements(fields) < 1) {
php_error_docref(NULL, E_WARNING, "Must pass at least one field");
return FAILURE;
}
// 3 because <key> FIELDS <num_fields>
argc = 3 + zend_hash_num_elements(fields);
redis_cmd_init_sstr(&cmdstr, argc, kw, strlen(kw));
redis_cmd_append_sstr_key_zstr(&cmdstr, key, redis_sock, slot);
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "FIELDS");
redis_cmd_append_sstr_long(&cmdstr, zend_hash_num_elements(fields));
ZEND_HASH_FOREACH_VAL(fields, zv)
field = zval_get_tmp_string(zv, &tmp);
redis_cmd_append_sstr_zstr(&cmdstr, field);
zend_tmp_string_release(tmp);
ZEND_HASH_FOREACH_END();
*cmd = cmdstr.c;
*cmd_len = cmdstr.len;
return SUCCESS;
}
int redis_hexpire_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char *kw, char **cmd, int *cmd_len, short *slot,
void **ctx)
{
zend_string *key, *option = NULL, *tmp, *field;
smart_string cmdstr = {0};
HashTable *fields;
zend_long ttl;
zval *zv;
int argc;
ZEND_PARSE_PARAMETERS_START(3, 4)
Z_PARAM_STR(key)
Z_PARAM_LONG(ttl)
Z_PARAM_ARRAY_HT(fields)
Z_PARAM_OPTIONAL
Z_PARAM_STR(option)
ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
if (zend_hash_num_elements(fields) < 1) {
php_error_docref(NULL, E_WARNING, "Must pass at least one field");
return FAILURE;
}
// 4 because <key> <ttl> FIELDS <num_fields>
argc = 4 + zend_hash_num_elements(fields) + (option ? 1 : 0);
redis_cmd_init_sstr(&cmdstr, argc, kw, strlen(kw));
redis_cmd_append_sstr_key_zstr(&cmdstr, key, redis_sock, slot);
redis_cmd_append_sstr_long(&cmdstr, ttl);
if (option) redis_cmd_append_sstr_zstr(&cmdstr, option);
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "FIELDS");
redis_cmd_append_sstr_long(&cmdstr, zend_hash_num_elements(fields));
ZEND_HASH_FOREACH_VAL(fields, zv)
field = zval_get_tmp_string(zv, &tmp);
redis_cmd_append_sstr_zstr(&cmdstr, field);
zend_tmp_string_release(tmp);
ZEND_HASH_FOREACH_END();
*cmd = cmdstr.c;
*cmd_len = cmdstr.len;
return SUCCESS;
}
/* MIGRATE */
int redis_migrate_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char **cmd, int *cmd_len, short *slot, void **ctx)

View File

@@ -356,6 +356,12 @@ int redis_expiremember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
int redis_expirememberat_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char **cmd, int *cmd_len, short *slot, void **ctx);
int redis_hexpire_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
int redis_httl_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw,
char **cmd, int *cmd_len, short *slot, void **ctx);
int redis_lmove_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 3a08bc16dd5a73e721e0df8f7843acdbbb585df5 */
* Stub hash: c6205649cd23ff2b9fcc63a034b601ee566ef236 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
ZEND_ARG_INFO(0, options)
@@ -412,6 +412,39 @@ ZEND_END_ARG_INFO()
#define arginfo_class_Redis_hVals arginfo_class_Redis__prefix
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_hexpire, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, ttl)
ZEND_ARG_INFO(0, fields)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
#define arginfo_class_Redis_hpexpire arginfo_class_Redis_hexpire
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_hexpireat, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, time)
ZEND_ARG_INFO(0, fields)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_hpexpireat, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, mstime)
ZEND_ARG_INFO(0, fields)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
#define arginfo_class_Redis_httl arginfo_class_Redis_hMget
#define arginfo_class_Redis_hpttl arginfo_class_Redis_hMget
#define arginfo_class_Redis_hexpiretime arginfo_class_Redis_hMget
#define arginfo_class_Redis_hpexpiretime arginfo_class_Redis_hMget
#define arginfo_class_Redis_hpersist arginfo_class_Redis_hMget
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_hscan, 0, 0, 2)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(1, iterator)
@@ -1134,6 +1167,15 @@ ZEND_METHOD(Redis, hSet);
ZEND_METHOD(Redis, hSetNx);
ZEND_METHOD(Redis, hStrLen);
ZEND_METHOD(Redis, hVals);
ZEND_METHOD(Redis, hexpire);
ZEND_METHOD(Redis, hpexpire);
ZEND_METHOD(Redis, hexpireat);
ZEND_METHOD(Redis, hpexpireat);
ZEND_METHOD(Redis, httl);
ZEND_METHOD(Redis, hpttl);
ZEND_METHOD(Redis, hexpiretime);
ZEND_METHOD(Redis, hpexpiretime);
ZEND_METHOD(Redis, hpersist);
ZEND_METHOD(Redis, hscan);
ZEND_METHOD(Redis, expiremember);
ZEND_METHOD(Redis, expirememberat);
@@ -1395,6 +1437,15 @@ static const zend_function_entry class_Redis_methods[] = {
ZEND_ME(Redis, hSetNx, arginfo_class_Redis_hSetNx, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hStrLen, arginfo_class_Redis_hStrLen, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hVals, arginfo_class_Redis_hVals, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hexpire, arginfo_class_Redis_hexpire, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hpexpire, arginfo_class_Redis_hpexpire, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hexpireat, arginfo_class_Redis_hexpireat, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hpexpireat, arginfo_class_Redis_hpexpireat, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, httl, arginfo_class_Redis_httl, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hpttl, arginfo_class_Redis_hpttl, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hexpiretime, arginfo_class_Redis_hexpiretime, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hpexpiretime, arginfo_class_Redis_hpexpiretime, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hpersist, arginfo_class_Redis_hpersist, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hscan, arginfo_class_Redis_hscan, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, expiremember, arginfo_class_Redis_expiremember, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, expirememberat, arginfo_class_Redis_expirememberat, ZEND_ACC_PUBLIC)

View File

@@ -6288,6 +6288,68 @@ class Redis_Test extends TestSuite {
}
}
public function testHashExpiration() {
if ( ! $this->minVersionCheck('7.4.0'))
$this->markTestSkipped();
$hexpire_cmds = [
'hexpire' => 10,
'hpexpire' => 10000,
'hexpireat' => time() + 10,
'hpexpireat' => time() * 1000 + 10000,
];
$httl_cmds = ['httl', 'hpttl', 'hexpiretime', 'hpexpiretime'];
$hash = ['Picard' => 'Enterprise', 'Sisko' => 'Defiant'];
$keys = array_keys($hash);
foreach ($hexpire_cmds as $exp_cmd => $ttl) {
$this->redis->del('hash');
$this->redis->hmset('hash', $hash);
/* Set a TTL on one existing and one non-existing field */
$res = $this->redis->{$exp_cmd}('hash', $ttl, ['Picard', 'nofield']);
$this->assertEquals($res, [1, -2]);
foreach ($httl_cmds as $ttl_cmd) {
$res = $this->redis->{$ttl_cmd}('hash', $keys);
$this->assertIsArray($res);
$this->assertEquals(count($keys), count($res));
/* Picard: has an expiry (>0), Siskto does not (<0) */
$this->assertTrue($res[0] > 0);
$this->assertTrue($res[1] < 0);
}
$this->redis->del('m');
$this->redis->hmset('m', ['F' => 'V']);
// NX - Only set expiry if it doesn't have one
foreach ([[1], [0]] as $expected) {
$res = $this->redis->{$exp_cmd}('m', $ttl, ['F'], 'NX');
$this->assertEquals($expected, $res);
}
// XX - Set if it has one
$res = $this->redis->{$exp_cmd}('m', $ttl, ['F'], 'XX');
$this->assertEquals([1], $res);
$this->redis->hpersist('m', ['F']);
$res = $this->redis->{$exp_cmd}('m', $ttl, ['F'], 'XX');
$this->assertEquals([0], $res);
// GT - should set if the new expiration is larger
$res = $this->redis->{$exp_cmd}('m', $ttl, ['F']);
$res = $this->redis->{$exp_cmd}('m', $ttl + 100, ['F'], 'GT');
$this->assertEquals([1], $res);
// LT - should not set if the new expiration is smaller
$res = $this->redis->{$exp_cmd}('m', $ttl / 2, ['F'], 'LT');
$this->assertTrue(is_array($res) && $res[0] > 0);
}
}
public function testHScan() {
if (version_compare($this->version, '2.8.0') < 0)
$this->markTestSkipped();