Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ff863f3

Browse files
committed
Refactor command command
Issue #2068
1 parent 872b693 commit ff863f3

8 files changed

Lines changed: 109 additions & 59 deletions

File tree

library.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,6 +1858,48 @@ redis_client_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval
18581858
return redis_client_trackinginfo_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
18591859
} else {
18601860
ZEND_ASSERT(!"memory corruption?");
1861+
return FAILURE;
1862+
}
1863+
}
1864+
1865+
static int
1866+
redis_command_info_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx)
1867+
{
1868+
int numElems;
1869+
zval z_ret;
1870+
1871+
if (read_mbulk_header(redis_sock, &numElems) < 0) {
1872+
if (IS_ATOMIC(redis_sock)) {
1873+
RETVAL_FALSE;
1874+
} else {
1875+
add_next_index_bool(z_tab, 0);
1876+
}
1877+
return FAILURE;
1878+
}
1879+
1880+
array_init(&z_ret);
1881+
redis_read_multibulk_recursive(redis_sock, numElems, 0, &z_ret);
1882+
if (IS_ATOMIC(redis_sock)) {
1883+
RETVAL_ZVAL(&z_ret, 0, 1);
1884+
} else {
1885+
add_next_index_zval(z_tab, &z_ret);
1886+
}
1887+
1888+
return SUCCESS;
1889+
}
1890+
1891+
PHP_REDIS_API int
1892+
redis_command_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx)
1893+
{
1894+
if (ctx == NULL) {
1895+
return redis_command_info_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1896+
} else if (ctx == PHPREDIS_CTX_PTR) {
1897+
return redis_long_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1898+
} else if (ctx == PHPREDIS_CTX_PTR + 1) {
1899+
return redis_mbulk_reply_raw(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1900+
} else {
1901+
ZEND_ASSERT(!"memory corruption?");
1902+
return FAILURE;
18611903
}
18621904
}
18631905

library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ PHP_REDIS_API int redis_hrandfield_response(INTERNAL_FUNCTION_PARAMETERS, RedisS
189189
PHP_REDIS_API int redis_pop_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
190190
PHP_REDIS_API int redis_lpos_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
191191
PHP_REDIS_API int redis_client_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
192+
PHP_REDIS_API int redis_command_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
192193

193194
/* Helper methods to get configuration values from a HashTable. */
194195

redis.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3077,7 +3077,7 @@ PHP_METHOD(Redis, rawcommand) {
30773077
* proto array Redis::command('info', string cmd)
30783078
* proto array Redis::command('getkeys', array cmd_args) */
30793079
PHP_METHOD(Redis, command) {
3080-
REDIS_PROCESS_CMD(command, redis_read_variant_reply);
3080+
REDIS_PROCESS_CMD(command, redis_command_response);
30813081
}
30823082
/* }}} */
30833083

redis.stub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ public function client(string $opt, mixed ...$args): mixed;
401401

402402
public function close(): bool;
403403

404-
public function command(string $opt = null, string|array $arg): mixed;
404+
public function command(string $opt = null, mixed ...$args): mixed;
405405

406406
/**
407407
* Execute the Redis CONFIG command in a variety of ways.

redis_arginfo.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 7230a9518fe0e79ae51f6b49d269053535a34199 */
2+
* Stub hash: b18973c6cdb4ae3a706dfd1ad5645339f0fcdd84 */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
55
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null")
@@ -120,9 +120,9 @@ ZEND_END_ARG_INFO()
120120

121121
#define arginfo_class_Redis_close arginfo_class_Redis_clearLastError
122122

123-
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_command, 0, 2, IS_MIXED, 0)
123+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_command, 0, 0, IS_MIXED, 0)
124124
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, opt, IS_STRING, 0, "null")
125-
ZEND_ARG_TYPE_MASK(0, arg, MAY_BE_STRING|MAY_BE_ARRAY, NULL)
125+
ZEND_ARG_VARIADIC_TYPE_INFO(0, args, IS_MIXED, 0)
126126
ZEND_END_ARG_INFO()
127127

128128
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_config, 0, 1, IS_MIXED, 0)

redis_commands.c

Lines changed: 38 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5245,64 +5245,51 @@ redis_client_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
52455245
int redis_command_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
52465246
char **cmd, int *cmd_len, short *slot, void **ctx)
52475247
{
5248-
char *kw=NULL;
5249-
zval *z_arg;
5250-
size_t kw_len;
5251-
5252-
/* Parse our args */
5253-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sz", &kw, &kw_len,
5254-
&z_arg) == FAILURE)
5255-
{
5256-
return FAILURE;
5257-
}
5248+
smart_string cmdstr = {0};
5249+
zend_string *op = NULL, *zstr;
5250+
zval *z_args = NULL;
5251+
int i, argc = 0;
52585252

5259-
/* Construct our command */
5260-
if (!kw) {
5261-
*cmd_len = REDIS_CMD_SPPRINTF(cmd, "COMMAND", "");
5262-
} else if (!z_arg) {
5263-
/* Sanity check */
5264-
if (strncasecmp(kw, "count", sizeof("count") - 1)) {
5265-
return FAILURE;
5266-
}
5267-
/* COMMAND COUNT */
5268-
*cmd_len = REDIS_CMD_SPPRINTF(cmd, "COMMAND", "s", "COUNT", sizeof("COUNT") - 1);
5269-
} else if (Z_TYPE_P(z_arg) == IS_STRING) {
5270-
/* Sanity check */
5271-
if (strncasecmp(kw, "info", sizeof("info") - 1)) {
5272-
return FAILURE;
5273-
}
5253+
ZEND_PARSE_PARAMETERS_START(0, -1)
5254+
Z_PARAM_OPTIONAL
5255+
Z_PARAM_STR(op)
5256+
Z_PARAM_VARIADIC('*', z_args, argc)
5257+
ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
52745258

5275-
/* COMMAND INFO <cmd> */
5276-
*cmd_len = REDIS_CMD_SPPRINTF(cmd, "COMMAND", "ss", "INFO", sizeof("INFO") - 1,
5277-
Z_STRVAL_P(z_arg), Z_STRLEN_P(z_arg));
5259+
if (op == NULL) {
5260+
*ctx = NULL;
5261+
argc = 0;
5262+
} else if (zend_string_equals_literal_ci(op, "COUNT")) {
5263+
*ctx = PHPREDIS_CTX_PTR;
5264+
argc = 0;
5265+
} else if (zend_string_equals_literal_ci(op, "DOCS") ||
5266+
zend_string_equals_literal_ci(op, "INFO")
5267+
) {
5268+
*ctx = NULL;
5269+
} else if (zend_string_equals_literal_ci(op, "GETKEYS") ||
5270+
zend_string_equals_literal_ci(op, "LIST")
5271+
) {
5272+
*ctx = PHPREDIS_CTX_PTR + 1;
5273+
} else if (zend_string_equals_literal_ci(op, "GETKEYSANDFLAGS")) {
5274+
*ctx = PHPREDIS_CTX_PTR + 2;
52785275
} else {
5279-
int arr_len;
5280-
5281-
/* Sanity check on args */
5282-
if (strncasecmp(kw, "getkeys", sizeof("getkeys")-1) ||
5283-
Z_TYPE_P(z_arg)!=IS_ARRAY ||
5284-
(arr_len=zend_hash_num_elements(Z_ARRVAL_P(z_arg)))<1)
5285-
{
5286-
return FAILURE;
5287-
}
5288-
5289-
zval *z_ele;
5290-
HashTable *ht_arr = Z_ARRVAL_P(z_arg);
5291-
smart_string cmdstr = {0};
5292-
5293-
redis_cmd_init_sstr(&cmdstr, 1 + arr_len, ZEND_STRL("COMMAND"));
5294-
redis_cmd_append_sstr(&cmdstr, ZEND_STRL("GETKEYS"));
5276+
php_error_docref(NULL, E_WARNING, "Unknown COMMAND operation '%s'", ZSTR_VAL(op));
5277+
return FAILURE;
5278+
}
52955279

5296-
ZEND_HASH_FOREACH_VAL(ht_arr, z_ele) {
5297-
zend_string *zstr = zval_get_string(z_ele);
5298-
redis_cmd_append_sstr(&cmdstr, ZSTR_VAL(zstr), ZSTR_LEN(zstr));
5299-
zend_string_release(zstr);
5300-
} ZEND_HASH_FOREACH_END();
5280+
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, !!op + argc, "COMMAND");
5281+
if (op) redis_cmd_append_sstr_zstr(&cmdstr, op);
53015282

5302-
*cmd = cmdstr.c;
5303-
*cmd_len = cmdstr.len;
5283+
for (i = 0; i < argc; ++i) {
5284+
zstr = zval_get_string(&z_args[i]);
5285+
redis_cmd_append_sstr(&cmdstr, ZSTR_VAL(zstr), ZSTR_LEN(zstr));
5286+
zend_string_release(zstr);
53045287
}
53055288

5289+
// Push out values
5290+
*cmd = cmdstr.c;
5291+
*cmd_len = cmdstr.len;
5292+
53065293
/* Any slot will do */
53075294
CMD_RAND_SLOT(slot);
53085295

redis_legacy_arginfo.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 7230a9518fe0e79ae51f6b49d269053535a34199 */
2+
* Stub hash: b18973c6cdb4ae3a706dfd1ad5645339f0fcdd84 */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
55
ZEND_ARG_INFO(0, options)
@@ -114,9 +114,9 @@ ZEND_END_ARG_INFO()
114114

115115
#define arginfo_class_Redis_close arginfo_class_Redis___destruct
116116

117-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_command, 0, 0, 2)
117+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_command, 0, 0, 0)
118118
ZEND_ARG_INFO(0, opt)
119-
ZEND_ARG_INFO(0, arg)
119+
ZEND_ARG_VARIADIC_INFO(0, args)
120120
ZEND_END_ARG_INFO()
121121

122122
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_config, 0, 0, 1)

tests/RedisTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7515,6 +7515,26 @@ public function testCopy()
75157515
$this->assertEquals('bar', $this->redis->get('key2'));
75167516
}
75177517

7518+
public function testCommand()
7519+
{
7520+
$commands = $this->redis->command();
7521+
$this->assertTrue(is_array($commands));
7522+
$this->assertEquals(count($commands), $this->redis->command('count'));
7523+
$infos = $this->redis->command('info');
7524+
$this->assertTrue(is_array($infos));
7525+
$this->assertEquals(count($infos), count($commands));
7526+
7527+
if (version_compare($this->version, '7.0') >= 0) {
7528+
$docs = $this->redis->command('docs');
7529+
$this->assertTrue(is_array($docs));
7530+
$this->assertEquals(count($docs), 2 * count($commands));
7531+
7532+
$list = $this->redis->command('list', 'filterby', 'pattern', 'lol*');
7533+
$this->assertTrue(is_array($list));
7534+
$this->assertEquals($list, ['lolwut']);
7535+
}
7536+
}
7537+
75187538
/* Make sure we handle a bad option value gracefully */
75197539
public function testBadOptionValue() {
75207540
$this->assertFalse(@$this->redis->setOption(pow(2, 32), false));

0 commit comments

Comments
 (0)