Skip to content

Commit 037dbbf

Browse files
committed
[WIP] Issue phpredis#1894
Add Redis::copy command
1 parent 1f2a7ef commit 037dbbf

File tree

5 files changed

+88
-0
lines changed

5 files changed

+88
-0
lines changed

php_redis.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ PHP_METHOD(Redis, bzPopMax);
4141
PHP_METHOD(Redis, bzPopMin);
4242
PHP_METHOD(Redis, close);
4343
PHP_METHOD(Redis, connect);
44+
PHP_METHOD(Redis, copy);
4445
PHP_METHOD(Redis, dbSize);
4546
PHP_METHOD(Redis, decr);
4647
PHP_METHOD(Redis, decrBy);

redis.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_config, 0, 0, 2)
134134
ZEND_ARG_INFO(0, value)
135135
ZEND_END_ARG_INFO()
136136

137+
ZEND_BEGIN_ARG_INFO_EX(arginfo_copy, 0, 0, 2)
138+
ZEND_ARG_INFO(0, source)
139+
ZEND_ARG_INFO(0, destination)
140+
ZEND_ARG_ARRAY_INFO(0, options, 0)
141+
ZEND_END_ARG_INFO()
142+
137143
ZEND_BEGIN_ARG_INFO_EX(arginfo_flush, 0, 0, 0)
138144
ZEND_ARG_INFO(0, async)
139145
ZEND_END_ARG_INFO()
@@ -283,6 +289,7 @@ static zend_function_entry redis_functions[] = {
283289
PHP_ME(Redis, command, arginfo_command, ZEND_ACC_PUBLIC)
284290
PHP_ME(Redis, config, arginfo_config, ZEND_ACC_PUBLIC)
285291
PHP_ME(Redis, connect, arginfo_connect, ZEND_ACC_PUBLIC)
292+
PHP_ME(Redis, copy, arginfo_copy, ZEND_ACC_PUBLIC)
286293
PHP_ME(Redis, dbSize, arginfo_void, ZEND_ACC_PUBLIC)
287294
PHP_ME(Redis, debug, arginfo_key, ZEND_ACC_PUBLIC)
288295
PHP_ME(Redis, decr, arginfo_key, ZEND_ACC_PUBLIC)
@@ -3535,6 +3542,12 @@ PHP_METHOD(Redis, command) {
35353542
}
35363543
/* }}} */
35373544

3545+
/* {{{ proto array Redis::copy(string $source, string $destination, array $options = null) */
3546+
PHP_METHOD(Redis, copy) {
3547+
REDIS_PROCESS_CMD(copy, redis_1_response)
3548+
}
3549+
/* }}} */
3550+
35383551
/* Helper to format any combination of SCAN arguments */
35393552
PHP_REDIS_API int
35403553
redis_build_scan_cmd(char **cmd, REDIS_SCAN_TYPE type, char *key, int key_len,

redis_commands.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3299,6 +3299,56 @@ int redis_command_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
32993299
return SUCCESS;
33003300
}
33013301

3302+
int
3303+
redis_copy_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
3304+
char **cmd, int *cmd_len, short *slot, void **ctx)
3305+
{
3306+
smart_string cmdstr = {0};
3307+
char *src, *dst;
3308+
size_t src_len, dst_len;
3309+
zend_long db = -1;
3310+
zend_bool replace = 0;
3311+
zval *opts = NULL;
3312+
3313+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|a",
3314+
&src, &src_len, &dst, &dst_len, &opts) == FAILURE)
3315+
{
3316+
return FAILURE;
3317+
}
3318+
3319+
if (opts != NULL && Z_TYPE_P(opts) == IS_ARRAY) {
3320+
zend_ulong idx;
3321+
zend_string *zkey;
3322+
zval *z_ele;
3323+
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(opts), idx, zkey, z_ele) {
3324+
if (zkey != NULL) {
3325+
ZVAL_DEREF(z_ele);
3326+
if (zend_string_equals_literal_ci(zkey, "db")) {
3327+
db = zval_get_long(z_ele);
3328+
} else if (zend_string_equals_literal_ci(zkey, "replace")) {
3329+
replace = zval_is_true(z_ele);
3330+
}
3331+
}
3332+
} ZEND_HASH_FOREACH_END();
3333+
}
3334+
3335+
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, 2 + (db > -1) + replace, "COPY");
3336+
redis_cmd_append_sstr(&cmdstr, src, src_len);
3337+
redis_cmd_append_sstr(&cmdstr, dst, dst_len);
3338+
3339+
if (db > -1) {
3340+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "DB");
3341+
redis_cmd_append_sstr_long(&cmdstr, db);
3342+
}
3343+
if (replace) {
3344+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "REPLACE");
3345+
}
3346+
3347+
*cmd = cmdstr.c;
3348+
*cmd_len = cmdstr.len;
3349+
return SUCCESS;
3350+
}
3351+
33023352
/* XADD */
33033353
int redis_xadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
33043354
char **cmd, int *cmd_len, short *slot, void **ctx)

redis_commands.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,9 @@ int redis_sdiffstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
259259
int redis_command_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
260260
char **cmd, int *cmd_len, short *slot, void **ctx);
261261

262+
int redis_copy_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
263+
char **cmd, int *cmd_len, short *slot, void **ctx);
264+
262265
int redis_fmt_scan_cmd(char **cmd, REDIS_SCAN_TYPE type, char *key, int key_len,
263266
long it, char *pat, int pat_len, long count);
264267

tests/RedisTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6571,6 +6571,27 @@ public function testTlsConnect()
65716571
}
65726572
}
65736573

6574+
public function testCopy()
6575+
{
6576+
// Only available since 6.2.0
6577+
if (version_compare($this->version, '6.2.0') < 0) {
6578+
$this->markTestSkipped();
6579+
return;
6580+
}
6581+
6582+
$this->redis->del('key2');
6583+
$this->redis->set('key', 'foo');
6584+
$this->assertTrue($this->redis->copy('key', 'key2'));
6585+
$this->assertEquals('foo', $this->redis->get('key2'));
6586+
6587+
$this->redis->set('key', 'bar');
6588+
$this->assertFalse($this->redis->copy('key', 'key2'));
6589+
$this->assertEquals('foo', $this->redis->get('key2'));
6590+
6591+
$this->assertTrue($this->redis->copy('key', 'key2', ['replace' => true]));
6592+
$this->assertEquals('bar', $this->redis->get('key2'));
6593+
}
6594+
65746595
public function testSession_regenerateSessionId_noLock_noDestroy() {
65756596
$this->setSessionHandler();
65766597
$sessionId = $this->generateSessionId();

0 commit comments

Comments
 (0)