diff options
author | Pavlo Yatsukhnenko <yatsukhnenko@gmail.com> | 2021-02-28 00:12:23 +0300 |
---|---|---|
committer | Pavlo Yatsukhnenko <yatsukhnenko@gmail.com> | 2021-02-28 00:17:20 +0300 |
commit | 037dbbf93db7db96633b0dd21c995b64af7aa1b9 (patch) | |
tree | 5a3c8a22dd57b1d2f9bfbbfa54da8db5a0d94fa3 | |
parent | 1f2a7ef6b5ea9c032e6075b2c21e0cf57bd11c3f (diff) |
[WIP] Issue #1894
Add Redis::copy command
-rw-r--r-- | php_redis.h | 1 | ||||
-rw-r--r-- | redis.c | 13 | ||||
-rw-r--r-- | redis_commands.c | 50 | ||||
-rw-r--r-- | redis_commands.h | 3 | ||||
-rw-r--r-- | tests/RedisTest.php | 21 |
5 files changed, 88 insertions, 0 deletions
diff --git a/php_redis.h b/php_redis.h index ab6533dd..ce5965f9 100644 --- a/php_redis.h +++ b/php_redis.h @@ -41,6 +41,7 @@ PHP_METHOD(Redis, bzPopMax); PHP_METHOD(Redis, bzPopMin); PHP_METHOD(Redis, close); PHP_METHOD(Redis, connect); +PHP_METHOD(Redis, copy); PHP_METHOD(Redis, dbSize); PHP_METHOD(Redis, decr); PHP_METHOD(Redis, decrBy); @@ -134,6 +134,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_config, 0, 0, 2) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_copy, 0, 0, 2) + ZEND_ARG_INFO(0, source) + ZEND_ARG_INFO(0, destination) + ZEND_ARG_ARRAY_INFO(0, options, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_flush, 0, 0, 0) ZEND_ARG_INFO(0, async) ZEND_END_ARG_INFO() @@ -283,6 +289,7 @@ static zend_function_entry redis_functions[] = { PHP_ME(Redis, command, arginfo_command, ZEND_ACC_PUBLIC) PHP_ME(Redis, config, arginfo_config, ZEND_ACC_PUBLIC) PHP_ME(Redis, connect, arginfo_connect, ZEND_ACC_PUBLIC) + PHP_ME(Redis, copy, arginfo_copy, ZEND_ACC_PUBLIC) PHP_ME(Redis, dbSize, arginfo_void, ZEND_ACC_PUBLIC) PHP_ME(Redis, debug, arginfo_key, ZEND_ACC_PUBLIC) PHP_ME(Redis, decr, arginfo_key, ZEND_ACC_PUBLIC) @@ -3535,6 +3542,12 @@ PHP_METHOD(Redis, command) { } /* }}} */ +/* {{{ proto array Redis::copy(string $source, string $destination, array $options = null) */ +PHP_METHOD(Redis, copy) { + REDIS_PROCESS_CMD(copy, redis_1_response) +} +/* }}} */ + /* Helper to format any combination of SCAN arguments */ PHP_REDIS_API int redis_build_scan_cmd(char **cmd, REDIS_SCAN_TYPE type, char *key, int key_len, diff --git a/redis_commands.c b/redis_commands.c index 85e23e46..027fbda0 100644 --- a/redis_commands.c +++ b/redis_commands.c @@ -3299,6 +3299,56 @@ int redis_command_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, return SUCCESS; } +int +redis_copy_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, + char **cmd, int *cmd_len, short *slot, void **ctx) +{ + smart_string cmdstr = {0}; + char *src, *dst; + size_t src_len, dst_len; + zend_long db = -1; + zend_bool replace = 0; + zval *opts = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|a", + &src, &src_len, &dst, &dst_len, &opts) == FAILURE) + { + return FAILURE; + } + + if (opts != NULL && Z_TYPE_P(opts) == IS_ARRAY) { + zend_ulong idx; + zend_string *zkey; + zval *z_ele; + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(opts), idx, 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_END(); + } + + REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, 2 + (db > -1) + replace, "COPY"); + redis_cmd_append_sstr(&cmdstr, src, src_len); + redis_cmd_append_sstr(&cmdstr, dst, dst_len); + + 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"); + } + + *cmd = cmdstr.c; + *cmd_len = cmdstr.len; + return SUCCESS; +} + /* XADD */ int redis_xadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char **cmd, int *cmd_len, short *slot, void **ctx) diff --git a/redis_commands.h b/redis_commands.h index a641851e..3a3e0491 100644 --- a/redis_commands.h +++ b/redis_commands.h @@ -259,6 +259,9 @@ int redis_sdiffstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, int redis_command_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char **cmd, int *cmd_len, short *slot, void **ctx); +int redis_copy_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, + char **cmd, int *cmd_len, short *slot, void **ctx); + int redis_fmt_scan_cmd(char **cmd, REDIS_SCAN_TYPE type, char *key, int key_len, long it, char *pat, int pat_len, long count); diff --git a/tests/RedisTest.php b/tests/RedisTest.php index 045bd4f8..95721350 100644 --- a/tests/RedisTest.php +++ b/tests/RedisTest.php @@ -6571,6 +6571,27 @@ class Redis_Test extends TestSuite } } + public function testCopy() + { + // Only available since 6.2.0 + if (version_compare($this->version, '6.2.0') < 0) { + $this->markTestSkipped(); + 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->set('key', 'bar'); + $this->assertFalse($this->redis->copy('key', 'key2')); + $this->assertEquals('foo', $this->redis->get('key2')); + + $this->assertTrue($this->redis->copy('key', 'key2', ['replace' => true])); + $this->assertEquals('bar', $this->redis->get('key2')); + } + public function testSession_regenerateSessionId_noLock_noDestroy() { $this->setSessionHandler(); $sessionId = $this->generateSessionId(); |