Skip to content

Commit fe39737

Browse files
committed
Add Redis::hRandField command
1 parent c65772f commit fe39737

10 files changed

Lines changed: 112 additions & 13 deletions

library.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,17 @@ redis_set_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_
13001300
return redis_string_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
13011301
}
13021302

1303+
PHP_REDIS_API int
1304+
redis_hrandfield_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx)
1305+
{
1306+
if (ctx == NULL) {
1307+
return redis_string_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1308+
} else if (ctx == PHPREDIS_CTX_PTR) {
1309+
return redis_mbulk_reply_raw(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1310+
}
1311+
return redis_mbulk_reply_zipped_raw(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1312+
}
1313+
13031314
PHP_REDIS_API int
13041315
redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
13051316
zval *z_tab, void *ctx,

library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ PHP_REDIS_API int redis_zrandmember_response(INTERNAL_FUNCTION_PARAMETERS, Redis
165165
PHP_REDIS_API int redis_zdiff_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
166166
PHP_REDIS_API int redis_set_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
167167
PHP_REDIS_API int redis_geosearch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
168+
PHP_REDIS_API int redis_hrandfield_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
168169

169170
/* Helper methods to get configuration values from a HashTable. */
170171

redis.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2219,6 +2219,14 @@ PHP_METHOD(Redis, hMset)
22192219
}
22202220
/* }}} */
22212221

2222+
/* {{{ proto bool Redis::hRandField(string key, [array $options]) */
2223+
PHP_METHOD(Redis, hRandField)
2224+
{
2225+
REDIS_PROCESS_CMD(hrandfield, redis_hrandfield_response);
2226+
}
2227+
/* }}} */
2228+
2229+
22222230
/* {{{ proto long Redis::hstrlen(string key, string field) */
22232231
PHP_METHOD(Redis, hStrLen) {
22242232
REDIS_PROCESS_CMD(hstrlen, redis_long_response);

redis.stub.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ public function hMget(string $key, array $keys): array;
193193

194194
public function hMset(string $key, array $keyvals): bool;
195195

196+
public function hRandField(string $key, array $options = null): string|array;
197+
196198
public function hSet(string $key, string $member, string $value): int;
197199

198200
public function hSetNx(string $key, string $member, string $value): int;

redis_arginfo.h

Lines changed: 9 additions & 5 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: 4b894d8f0c04d6c25398e5dc399598d0ede4ed05 */
2+
* Stub hash: 452d7bafe0b4a9d6d67353613d9cde2d407aa2a2 */
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")
@@ -334,6 +334,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_hMset, 0, 2, _IS_BOO
334334
ZEND_ARG_TYPE_INFO(0, keyvals, IS_ARRAY, 0)
335335
ZEND_END_ARG_INFO()
336336

337+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Redis_hRandField, 0, 1, MAY_BE_STRING|MAY_BE_ARRAY)
338+
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
339+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null")
340+
ZEND_END_ARG_INFO()
341+
337342
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_hSet, 0, 3, IS_LONG, 0)
338343
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
339344
ZEND_ARG_TYPE_INFO(0, member, IS_STRING, 0)
@@ -888,10 +893,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_zRangeByScore, 0, 3,
888893
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]")
889894
ZEND_END_ARG_INFO()
890895

891-
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Redis_zRandMember, 0, 1, MAY_BE_STRING|MAY_BE_ARRAY)
892-
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
893-
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null")
894-
ZEND_END_ARG_INFO()
896+
#define arginfo_class_Redis_zRandMember arginfo_class_Redis_hRandField
895897

896898
#define arginfo_class_Redis_zRank arginfo_class_Redis_hStrLen
897899

@@ -1030,6 +1032,7 @@ ZEND_METHOD(Redis, hKeys);
10301032
ZEND_METHOD(Redis, hLen);
10311033
ZEND_METHOD(Redis, hMget);
10321034
ZEND_METHOD(Redis, hMset);
1035+
ZEND_METHOD(Redis, hRandField);
10331036
ZEND_METHOD(Redis, hSet);
10341037
ZEND_METHOD(Redis, hSetNx);
10351038
ZEND_METHOD(Redis, hStrLen);
@@ -1257,6 +1260,7 @@ static const zend_function_entry class_Redis_methods[] = {
12571260
ZEND_ME(Redis, hLen, arginfo_class_Redis_hLen, ZEND_ACC_PUBLIC)
12581261
ZEND_ME(Redis, hMget, arginfo_class_Redis_hMget, ZEND_ACC_PUBLIC)
12591262
ZEND_ME(Redis, hMset, arginfo_class_Redis_hMset, ZEND_ACC_PUBLIC)
1263+
ZEND_ME(Redis, hRandField, arginfo_class_Redis_hRandField, ZEND_ACC_PUBLIC)
12601264
ZEND_ME(Redis, hSet, arginfo_class_Redis_hSet, ZEND_ACC_PUBLIC)
12611265
ZEND_ME(Redis, hSetNx, arginfo_class_Redis_hSetNx, ZEND_ACC_PUBLIC)
12621266
ZEND_ME(Redis, hStrLen, arginfo_class_Redis_hStrLen, ZEND_ACC_PUBLIC)

redis_commands.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,6 +2548,54 @@ int redis_hsetnx_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
25482548
cmd, cmd_len, slot);
25492549
}
25502550

2551+
int
2552+
redis_hrandfield_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
2553+
char **cmd, int *cmd_len, short *slot, void **ctx)
2554+
{
2555+
char *key;
2556+
int count = 0;
2557+
size_t key_len;
2558+
smart_string cmdstr = {0};
2559+
zend_bool withvalues = 0;
2560+
zval *z_opts = NULL, *z_ele;
2561+
2562+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a",
2563+
&key, &key_len, &z_opts) == FAILURE)
2564+
{
2565+
return FAILURE;
2566+
}
2567+
2568+
if (z_opts && Z_TYPE_P(z_opts) == IS_ARRAY) {
2569+
zend_string *zkey;
2570+
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(z_opts), zkey, z_ele) {
2571+
ZVAL_DEREF(z_ele);
2572+
if (zend_string_equals_literal_ci(zkey, "count")) {
2573+
count = zval_get_long(z_ele);
2574+
} else if (zend_string_equals_literal_ci(zkey, "withvalues")) {
2575+
withvalues = zval_is_true(z_ele);
2576+
}
2577+
} ZEND_HASH_FOREACH_END();
2578+
}
2579+
2580+
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, 1 + (count != 0) + withvalues, "HRANDFIELD");
2581+
redis_cmd_append_sstr_key(&cmdstr, key, key_len, redis_sock, slot);
2582+
2583+
if (count != 0) {
2584+
redis_cmd_append_sstr_long(&cmdstr, count);
2585+
*ctx = PHPREDIS_CTX_PTR;
2586+
}
2587+
2588+
if (withvalues) {
2589+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "WITHVALUES");
2590+
*ctx = PHPREDIS_CTX_PTR + 1;
2591+
}
2592+
2593+
2594+
*cmd = cmdstr.c;
2595+
*cmd_len = cmdstr.len;
2596+
return SUCCESS;
2597+
}
2598+
25512599
/* SRANDMEMBER */
25522600
int redis_srandmember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
25532601
char **cmd, int *cmd_len, short *slot, void **ctx,
@@ -3299,7 +3347,6 @@ redis_geosearch_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
32993347
{
33003348
char *key, *unit;
33013349
int argc = 2;
3302-
short store_slot = 0;
33033350
size_t keylen, unitlen;
33043351
geoOptions gopts = {0};
33053352
smart_string cmdstr = {0};
@@ -3423,7 +3470,6 @@ redis_geosearchstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
34233470
{
34243471
int argc = 3;
34253472
char *dest, *src, *unit;
3426-
short store_slot = 0;
34273473
size_t destlen, srclen, unitlen;
34283474
geoOptions gopts = {0};
34293475
smart_string cmdstr = {0};

redis_commands.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ int redis_lrem_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
219219
int redis_smove_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
220220
char **cmd, int *cmd_len, short *slot, void **ctx);
221221

222+
int redis_hrandfield_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
223+
char **cmd, int *cmd_len, short *slot, void **ctx);
224+
222225
int redis_hset_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
223226
char **cmd, int *cmd_len, short *slot, void **ctx);
224227

redis_legacy_arginfo.h

Lines changed: 10 additions & 6 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: 4b894d8f0c04d6c25398e5dc399598d0ede4ed05 */
2+
* Stub hash: 452d7bafe0b4a9d6d67353613d9cde2d407aa2a2 */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
55
ZEND_ARG_INFO(0, options)
@@ -304,6 +304,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_hMset, 0, 0, 2)
304304
ZEND_ARG_INFO(0, keyvals)
305305
ZEND_END_ARG_INFO()
306306

307+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_hRandField, 0, 0, 1)
308+
ZEND_ARG_INFO(0, key)
309+
ZEND_ARG_INFO(0, options)
310+
ZEND_END_ARG_INFO()
311+
307312
#define arginfo_class_Redis_hSet arginfo_class_Redis_hIncrBy
308313

309314
#define arginfo_class_Redis_hSetNx arginfo_class_Redis_hIncrBy
@@ -602,10 +607,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_slowlog, 0, 0, 1)
602607
ZEND_ARG_INFO(0, option)
603608
ZEND_END_ARG_INFO()
604609

605-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_sort, 0, 0, 1)
606-
ZEND_ARG_INFO(0, key)
607-
ZEND_ARG_INFO(0, options)
608-
ZEND_END_ARG_INFO()
610+
#define arginfo_class_Redis_sort arginfo_class_Redis_hRandField
609611

610612
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_sortAsc, 0, 0, 1)
611613
ZEND_ARG_INFO(0, key)
@@ -800,7 +802,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_zRangeByScore, 0, 0, 3)
800802
ZEND_ARG_INFO(0, options)
801803
ZEND_END_ARG_INFO()
802804

803-
#define arginfo_class_Redis_zRandMember arginfo_class_Redis_sort
805+
#define arginfo_class_Redis_zRandMember arginfo_class_Redis_hRandField
804806

805807
#define arginfo_class_Redis_zRank arginfo_class_Redis_hExists
806808

@@ -932,6 +934,7 @@ ZEND_METHOD(Redis, hKeys);
932934
ZEND_METHOD(Redis, hLen);
933935
ZEND_METHOD(Redis, hMget);
934936
ZEND_METHOD(Redis, hMset);
937+
ZEND_METHOD(Redis, hRandField);
935938
ZEND_METHOD(Redis, hSet);
936939
ZEND_METHOD(Redis, hSetNx);
937940
ZEND_METHOD(Redis, hStrLen);
@@ -1159,6 +1162,7 @@ static const zend_function_entry class_Redis_methods[] = {
11591162
ZEND_ME(Redis, hLen, arginfo_class_Redis_hLen, ZEND_ACC_PUBLIC)
11601163
ZEND_ME(Redis, hMget, arginfo_class_Redis_hMget, ZEND_ACC_PUBLIC)
11611164
ZEND_ME(Redis, hMset, arginfo_class_Redis_hMset, ZEND_ACC_PUBLIC)
1165+
ZEND_ME(Redis, hRandField, arginfo_class_Redis_hRandField, ZEND_ACC_PUBLIC)
11621166
ZEND_ME(Redis, hSet, arginfo_class_Redis_hSet, ZEND_ACC_PUBLIC)
11631167
ZEND_ME(Redis, hSetNx, arginfo_class_Redis_hSetNx, ZEND_ACC_PUBLIC)
11641168
ZEND_ME(Redis, hStrLen, arginfo_class_Redis_hStrLen, ZEND_ACC_PUBLIC)

tests/RedisClusterTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public function testZRandMember() { return $this->marktestSkipped(); }
6161
public function testCopy() { return $this->marktestSkipped(); }
6262
public function testGeoSearch() { return $this->marktestSkipped(); }
6363
public function testGeoSearchStore() { return $this->marktestSkipped(); }
64+
public function testHRandField() { return $this->marktestSkipped(); }
6465

6566
/* Session locking feature is currently not supported in in context of Redis Cluster.
6667
The biggest issue for this is the distribution nature of Redis cluster */

tests/RedisTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2846,6 +2846,25 @@ public function testHashes() {
28462846
}
28472847
}
28482848

2849+
public function testHRandField()
2850+
{
2851+
if (version_compare($this->version, "6.2.0") < 0) {
2852+
$this->MarkTestSkipped();
2853+
return;
2854+
}
2855+
$this->redis->del('key');
2856+
$this->redis->hMSet('key', ['a' => 0, 'b' => 1, 'c' => 'foo', 'd' => 'bar', 'e' => null]);
2857+
$this->assertInArray($this->redis->hRandField('key'), ['a', 'b', 'c', 'd', 'e']);
2858+
2859+
$result = $this->redis->hRandField('key', ['count' => 3]);
2860+
$this->assertEquals(3, count($result));
2861+
$this->assertEquals(array_intersect($result, ['a', 'b', 'c', 'd', 'e']), $result);
2862+
2863+
$result = $this->redis->hRandField('key', ['count' => 2, 'withvalues' => true]);
2864+
$this->assertEquals(2, count($result));
2865+
$this->assertEquals(array_intersect_key($result, ['a' => 0, 'b' => 1, 'c' => 'foo', 'd' => 'bar', 'e' => null]), $result);
2866+
}
2867+
28492868
public function testSetRange() {
28502869

28512870
$this->redis->del('key');

0 commit comments

Comments
 (0)