mirror of
https://github.com/php-win-ext/phpredis.git
synced 2026-03-24 00:52:16 +01:00
Implement COPY for RedisCluster
* Refactor `redis_copy_cmd` to use the new argument parsing macros. * Add a handler in `RedisCluster`. See #1894
This commit is contained in:
committed by
Michael Grunder
parent
e222b85ecf
commit
40a2c254e2
@@ -3142,5 +3142,9 @@ PHP_METHOD(RedisCluster, command) {
|
||||
CLUSTER_PROCESS_CMD(command, cluster_variant_resp, 0);
|
||||
}
|
||||
|
||||
PHP_METHOD(RedisCluster, copy) {
|
||||
CLUSTER_PROCESS_CMD(copy, cluster_1_resp, 0)
|
||||
}
|
||||
|
||||
/* vim: set tabstop=4 softtabstop=4 expandtab shiftwidth=4: */
|
||||
|
||||
|
||||
@@ -227,6 +227,11 @@ class RedisCluster {
|
||||
*/
|
||||
public function dbsize(string|array $key_or_address): RedisCluster|int;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/copy
|
||||
*/
|
||||
public function copy(string $src, string $dst, array $options = null): RedisCluster|bool;
|
||||
|
||||
/**
|
||||
* @see Redis::decr()
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 2225d10403eb94c52ad017310e783115b9ea869e */
|
||||
* Stub hash: e6c2d8efa4150e1cb198470d8106e693661c1e4f */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 1)
|
||||
@@ -165,6 +165,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_dbsize, 0
|
||||
ZEND_ARG_TYPE_MASK(0, key_or_address, MAY_BE_STRING|MAY_BE_ARRAY, NULL)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_copy, 0, 2, RedisCluster, MAY_BE_BOOL)
|
||||
ZEND_ARG_TYPE_INFO(0, src, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, dst, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_decr, 0, 1, RedisCluster, MAY_BE_LONG|MAY_BE_FALSE)
|
||||
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, by, IS_LONG, 0, "1")
|
||||
@@ -1042,6 +1048,7 @@ ZEND_METHOD(RedisCluster, cluster);
|
||||
ZEND_METHOD(RedisCluster, command);
|
||||
ZEND_METHOD(RedisCluster, config);
|
||||
ZEND_METHOD(RedisCluster, dbsize);
|
||||
ZEND_METHOD(RedisCluster, copy);
|
||||
ZEND_METHOD(RedisCluster, decr);
|
||||
ZEND_METHOD(RedisCluster, decrby);
|
||||
ZEND_METHOD(RedisCluster, decrbyfloat);
|
||||
@@ -1260,6 +1267,7 @@ static const zend_function_entry class_RedisCluster_methods[] = {
|
||||
ZEND_ME(RedisCluster, command, arginfo_class_RedisCluster_command, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, config, arginfo_class_RedisCluster_config, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, dbsize, arginfo_class_RedisCluster_dbsize, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, copy, arginfo_class_RedisCluster_copy, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, decr, arginfo_class_RedisCluster_decr, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, decrby, arginfo_class_RedisCluster_decrby, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, decrbyfloat, arginfo_class_RedisCluster_decrbyfloat, ZEND_ACC_PUBLIC)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 2225d10403eb94c52ad017310e783115b9ea869e */
|
||||
* Stub hash: e6c2d8efa4150e1cb198470d8106e693661c1e4f */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, name)
|
||||
@@ -151,6 +151,12 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_RedisCluster_dbsize arginfo_class_RedisCluster_bgrewriteaof
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_copy, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, src)
|
||||
ZEND_ARG_INFO(0, dst)
|
||||
ZEND_ARG_INFO(0, options)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_decr, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, key)
|
||||
ZEND_ARG_INFO(0, by)
|
||||
@@ -886,6 +892,7 @@ ZEND_METHOD(RedisCluster, cluster);
|
||||
ZEND_METHOD(RedisCluster, command);
|
||||
ZEND_METHOD(RedisCluster, config);
|
||||
ZEND_METHOD(RedisCluster, dbsize);
|
||||
ZEND_METHOD(RedisCluster, copy);
|
||||
ZEND_METHOD(RedisCluster, decr);
|
||||
ZEND_METHOD(RedisCluster, decrby);
|
||||
ZEND_METHOD(RedisCluster, decrbyfloat);
|
||||
@@ -1104,6 +1111,7 @@ static const zend_function_entry class_RedisCluster_methods[] = {
|
||||
ZEND_ME(RedisCluster, command, arginfo_class_RedisCluster_command, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, config, arginfo_class_RedisCluster_config, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, dbsize, arginfo_class_RedisCluster_dbsize, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, copy, arginfo_class_RedisCluster_copy, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, decr, arginfo_class_RedisCluster_decr, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, decrby, arginfo_class_RedisCluster_decrby, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, decrbyfloat, arginfo_class_RedisCluster_decrbyfloat, ZEND_ACC_PUBLIC)
|
||||
|
||||
@@ -5345,44 +5345,56 @@ int
|
||||
redis_copy_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx)
|
||||
{
|
||||
zend_string *src = NULL, *dst = NULL;
|
||||
smart_string cmdstr = {0};
|
||||
char *src, *dst;
|
||||
size_t src_len, dst_len;
|
||||
zend_long db = -1;
|
||||
HashTable *opts = NULL;
|
||||
zend_bool replace = 0;
|
||||
zval *opts = NULL, *z_ele;
|
||||
zend_string *zkey;
|
||||
zend_long db = -1;
|
||||
short slot2;
|
||||
zval *zv;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|a",
|
||||
&src, &src_len, &dst, &dst_len, &opts) == FAILURE)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
ZEND_PARSE_PARAMETERS_START(2, 3)
|
||||
Z_PARAM_STR(src)
|
||||
Z_PARAM_STR(dst)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_ARRAY_HT_OR_NULL(opts)
|
||||
ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
|
||||
|
||||
if (opts != NULL) {
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(opts), zkey, z_ele) {
|
||||
if (zkey != NULL) {
|
||||
ZVAL_DEREF(z_ele);
|
||||
if (zend_string_equals_literal_ci(zkey, "db")) {
|
||||
db = zval_get_long(z_ele);
|
||||
} else if (zend_string_equals_literal_ci(zkey, "replace")) {
|
||||
replace = zval_is_true(z_ele);
|
||||
}
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(opts, zkey, zv) {
|
||||
if (zkey == NULL)
|
||||
continue;
|
||||
|
||||
ZVAL_DEREF(zv);
|
||||
if (zend_string_equals_literal_ci(zkey, "db")) {
|
||||
db = zval_get_long(zv);
|
||||
} else if (zend_string_equals_literal_ci(zkey, "replace")) {
|
||||
replace = zval_is_true(zv);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
|
||||
if (slot && db != -1) {
|
||||
php_error_docref(NULL, E_WARNING, "Cant copy to a specific DB in cluster mode");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, 2 + (db > -1 ? 2 : 0) + replace, "COPY");
|
||||
redis_cmd_append_sstr(&cmdstr, src, src_len);
|
||||
redis_cmd_append_sstr(&cmdstr, dst, dst_len);
|
||||
redis_cmd_append_sstr_key_zstr(&cmdstr, src, redis_sock, slot);
|
||||
redis_cmd_append_sstr_key_zstr(&cmdstr, dst, redis_sock, slot ? &slot2 : NULL);
|
||||
|
||||
if (slot && *slot != slot2) {
|
||||
php_error_docref(NULL, E_WARNING, "Keys must hash to the same slot!");
|
||||
efree(cmdstr.c);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (db > -1) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "DB");
|
||||
redis_cmd_append_sstr_long(&cmdstr, db);
|
||||
}
|
||||
if (replace) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "REPLACE");
|
||||
}
|
||||
REDIS_CMD_APPEND_SSTR_OPT_STATIC(&cmdstr, replace, "REPLACE");
|
||||
|
||||
*cmd = cmdstr.c;
|
||||
*cmd_len = cmdstr.len;
|
||||
|
||||
@@ -57,7 +57,6 @@ class Redis_Cluster_Test extends Redis_Test {
|
||||
public function testzDiffStore() { return $this->markTestSkipped(); }
|
||||
public function testzMscore() { return $this->marktestSkipped(); }
|
||||
public function testZRandMember() { return $this->marktestSkipped(); }
|
||||
public function testCopy() { return $this->marktestSkipped(); }
|
||||
public function testConfig() { return $this->markTestSkipped(); }
|
||||
public function testFlushDB() { return $this->markTestSkipped(); }
|
||||
|
||||
|
||||
@@ -7531,17 +7531,17 @@ class Redis_Test extends TestSuite
|
||||
return;
|
||||
}
|
||||
|
||||
$this->redis->del('key2');
|
||||
$this->redis->set('key', 'foo');
|
||||
$this->assertTrue($this->redis->copy('key', 'key2'));
|
||||
$this->assertEquals('foo', $this->redis->get('key2'));
|
||||
$this->redis->del('{key}dst');
|
||||
$this->redis->set('{key}src', 'foo');
|
||||
$this->assertTrue($this->redis->copy('{key}src', '{key}dst'));
|
||||
$this->assertEquals('foo', $this->redis->get('{key}dst'));
|
||||
|
||||
$this->redis->set('key', 'bar');
|
||||
$this->assertFalse($this->redis->copy('key', 'key2'));
|
||||
$this->assertEquals('foo', $this->redis->get('key2'));
|
||||
$this->redis->set('{key}src', 'bar');
|
||||
$this->assertFalse($this->redis->copy('{key}src', '{key}dst'));
|
||||
$this->assertEquals('foo', $this->redis->get('{key}dst'));
|
||||
|
||||
$this->assertTrue($this->redis->copy('key', 'key2', ['replace' => true]));
|
||||
$this->assertEquals('bar', $this->redis->get('key2'));
|
||||
$this->assertTrue($this->redis->copy('{key}src', '{key}dst', ['replace' => true]));
|
||||
$this->assertEquals('bar', $this->redis->get('{key}dst'));
|
||||
}
|
||||
|
||||
public function testCommand()
|
||||
|
||||
Reference in New Issue
Block a user