mirror of
https://github.com/php-win-ext/phpredis.git
synced 2026-03-24 00:52:16 +01:00
Implement Valkey >= 8.1 IFEQ set option
Implement the new `IFEQ` `SET` option that will be included in `Valkey` 8.1. See: valkey-io/valkey#1324
This commit is contained in:
committed by
Michael Grunder
parent
faa4bc2086
commit
a2eef77f44
@@ -2293,7 +2293,8 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx)
|
||||
{
|
||||
char *key = NULL, *exp_type = NULL, *set_type = NULL;
|
||||
zval *z_value, *z_opts=NULL;
|
||||
zend_string *ifeq = NULL, *tmp = NULL;
|
||||
zval *z_value, *z_opts = NULL;
|
||||
smart_string cmdstr = {0};
|
||||
zend_long expire = -1;
|
||||
zend_bool get = 0;
|
||||
@@ -2312,7 +2313,6 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// Check for an options array
|
||||
if (z_opts && Z_TYPE_P(z_opts) == IS_ARRAY) {
|
||||
HashTable *kt = Z_ARRVAL_P(z_opts);
|
||||
@@ -2329,11 +2329,14 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zend_string_equals_literal_ci(zkey, "PXAT"))
|
||||
) {
|
||||
if (redis_try_get_expiry(v, &expire) == FAILURE || expire < 1) {
|
||||
zend_tmp_string_release(tmp);
|
||||
setExpiryWarning(v);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
exp_type = ZSTR_VAL(zkey);
|
||||
} else if (zkey && !ifeq && zend_string_equals_literal_ci(zkey, "IFEQ")) {
|
||||
ifeq = zval_get_tmp_string(v, &tmp);
|
||||
} else if (Z_TYPE_P(v) == IS_STRING) {
|
||||
if (zend_string_equals_literal_ci(Z_STR_P(v), "KEEPTTL")) {
|
||||
keep_ttl = 1;
|
||||
@@ -2348,6 +2351,7 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} else if (z_opts && Z_TYPE_P(z_opts) != IS_NULL) {
|
||||
if (redis_try_get_expiry(z_opts, &expire) == FAILURE || expire < 1) {
|
||||
zend_tmp_string_release(tmp);
|
||||
setExpiryWarning(z_opts);
|
||||
return FAILURE;
|
||||
}
|
||||
@@ -2356,6 +2360,14 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
/* Protect the user from syntax errors but give them some info about what's wrong */
|
||||
if (exp_type && keep_ttl) {
|
||||
php_error_docref(NULL, E_WARNING, "KEEPTTL can't be combined with EX or PX option");
|
||||
zend_tmp_string_release(tmp);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* You can't use IFEQ with NX or XX */
|
||||
if (set_type && ifeq) {
|
||||
php_error_docref(NULL, E_WARNING, "IFEQ can't be combined with NX or XX option");
|
||||
zend_tmp_string_release(tmp);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@@ -2363,11 +2375,13 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
* actually execute a SETEX command */
|
||||
if (expire > 0 && !exp_type && !set_type && !keep_ttl) {
|
||||
*cmd_len = REDIS_CMD_SPPRINTF(cmd, "SETEX", "klv", key, key_len, expire, z_value);
|
||||
zend_tmp_string_release(tmp);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* Calculate argc based on options set */
|
||||
int argc = 2 + (exp_type ? 2 : 0) + (set_type != NULL) + (keep_ttl != 0) + get;
|
||||
int argc = 2 + (ifeq ? 2 : 0) + (exp_type ? 2 : 0) + (set_type != NULL) +
|
||||
(keep_ttl != 0) + get;
|
||||
|
||||
/* Initial SET <key> <value> */
|
||||
redis_cmd_init_sstr(&cmdstr, argc, "SET", 3);
|
||||
@@ -2379,8 +2393,13 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
redis_cmd_append_sstr_long(&cmdstr, (long)expire);
|
||||
}
|
||||
|
||||
if (set_type)
|
||||
if (ifeq) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "IFEQ");
|
||||
redis_cmd_append_sstr_zstr(&cmdstr, ifeq);
|
||||
} else if (set_type) {
|
||||
redis_cmd_append_sstr(&cmdstr, set_type, strlen(set_type));
|
||||
}
|
||||
|
||||
if (keep_ttl)
|
||||
redis_cmd_append_sstr(&cmdstr, "KEEPTTL", 7);
|
||||
if (get) {
|
||||
@@ -2388,6 +2407,8 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
*ctx = PHPREDIS_CTX_PTR;
|
||||
}
|
||||
|
||||
zend_tmp_string_release(tmp);
|
||||
|
||||
/* Push command and length to the caller */
|
||||
*cmd = cmdstr.c;
|
||||
*cmd_len = cmdstr.len;
|
||||
|
||||
@@ -133,6 +133,7 @@ class Redis_Cluster_Test extends Redis_Test {
|
||||
$info = $this->redis->info(uniqid());
|
||||
$this->version = $info['redis_version'] ?? '0.0.0';
|
||||
$this->is_keydb = $this->detectKeyDB($info);
|
||||
$this->is_valkey = $this->detectValkey($info);
|
||||
}
|
||||
|
||||
/* Override newInstance as we want a RedisCluster object */
|
||||
|
||||
@@ -67,11 +67,16 @@ class Redis_Test extends TestSuite {
|
||||
isset($info['mvcc_depth']);
|
||||
}
|
||||
|
||||
protected function detectValkey(array $info) {
|
||||
return isset($info['server_name']) && $info['server_name'] === 'valkey';
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
$this->redis = $this->newInstance();
|
||||
$info = $this->redis->info();
|
||||
$this->version = (isset($info['redis_version'])?$info['redis_version']:'0.0.0');
|
||||
$this->is_keydb = $this->detectKeyDB($info);
|
||||
$this->is_valkey = $this->detectValKey($info);
|
||||
}
|
||||
|
||||
protected function minVersionCheck($version) {
|
||||
@@ -629,6 +634,19 @@ class Redis_Test extends TestSuite {
|
||||
$this->assertEquals('bar', $this->redis->set('foo', 'baz', ['GET']));
|
||||
}
|
||||
|
||||
/* Test Valkey >= 8.1 IFEQ SET option */
|
||||
public function testValkeyIfEq() {
|
||||
if ( ! $this->is_valkey || ! $this->minVersionCheck('8.1.0'))
|
||||
$this->markTestSkipped();
|
||||
|
||||
$this->redis->del('foo');
|
||||
$this->assertTrue($this->redis->set('foo', 'bar'));
|
||||
$this->assertTrue($this->redis->set('foo', 'bar2', ['IFEQ' => 'bar']));
|
||||
$this->assertFalse($this->redis->set('foo', 'bar4', ['IFEQ' => 'bar3']));
|
||||
|
||||
$this->assertEquals('bar2', $this->redis->set('foo', 'bar3', ['IFEQ' => 'bar2', 'GET']));
|
||||
}
|
||||
|
||||
public function testGetSet() {
|
||||
$this->redis->del('key');
|
||||
$this->assertFalse($this->redis->getSet('key', '42'));
|
||||
|
||||
@@ -16,6 +16,7 @@ class TestSuite
|
||||
/* Redis server version */
|
||||
protected $version;
|
||||
protected bool $is_keydb;
|
||||
protected bool $is_valkey;
|
||||
|
||||
private static bool $colorize = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user