Skip to content

Commit 99f9fd8

Browse files
authoredJul 14, 2024
Fix HRANDFIELD command when WITHVALUES is used. (#2524)
Redis requires the user to send a count if `WITHVALUES` is specified, otherwise it sees the `WITHVALUES` argument as the count and will error out that it's not a number. We can also return false if the key doesn't exist.
1 parent eeb5109 commit 99f9fd8

File tree

5 files changed

+26
-5
lines changed

5 files changed

+26
-5
lines changed
 

‎redis.stub.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -1798,7 +1798,7 @@ public function hMset(string $key, array $fieldvals): Redis|bool;
17981798
* @example $redis->hrandfield('settings');
17991799
* @example $redis->hrandfield('settings', ['count' => 2, 'withvalues' => true]);
18001800
*/
1801-
public function hRandField(string $key, ?array $options = null): Redis|string|array;
1801+
public function hRandField(string $key, ?array $options = null): Redis|string|array|false;
18021802

18031803
public function hSet(string $key, string $member, mixed $value): Redis|int|false;
18041804

‎redis_arginfo.h

+6-3
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: 04fe88bbcc4d3dc3be06385e8931dfb080442f23 */
2+
* Stub hash: 70b942571cb2e3ef0b2531492840d9207f693b00 */
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, 1, "null")
@@ -434,7 +434,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hMset, 0, 2, Red
434434
ZEND_ARG_TYPE_INFO(0, fieldvals, IS_ARRAY, 0)
435435
ZEND_END_ARG_INFO()
436436

437-
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hRandField, 0, 1, Redis, MAY_BE_STRING|MAY_BE_ARRAY)
437+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hRandField, 0, 1, Redis, MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_FALSE)
438438
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
439439
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null")
440440
ZEND_END_ARG_INFO()
@@ -1069,7 +1069,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_zrangestore, 0,
10691069
ZEND_ARG_TYPE_MASK(0, options, MAY_BE_ARRAY|MAY_BE_BOOL|MAY_BE_NULL, "null")
10701070
ZEND_END_ARG_INFO()
10711071

1072-
#define arginfo_class_Redis_zRandMember arginfo_class_Redis_hRandField
1072+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_zRandMember, 0, 1, Redis, MAY_BE_STRING|MAY_BE_ARRAY)
1073+
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
1074+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null")
1075+
ZEND_END_ARG_INFO()
10731076

10741077
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_zRank, 0, 2, Redis, MAY_BE_LONG|MAY_BE_FALSE)
10751078
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)

‎redis_commands.c

+8
Original file line numberDiff line numberDiff line change
@@ -3577,10 +3577,18 @@ redis_hrandfield_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
35773577
} else if (zend_string_equals_literal_ci(zkey, "withvalues")) {
35783578
withvalues = zval_is_true(z_ele);
35793579
}
3580+
} else if (Z_TYPE_P(z_ele) == IS_STRING) {
3581+
if (zend_string_equals_literal_ci(Z_STR_P(z_ele), "WITHVALUES")) {
3582+
withvalues = 1;
3583+
}
35803584
}
35813585
} ZEND_HASH_FOREACH_END();
35823586
}
35833587

3588+
/* If we're sending WITHVALUES we must also send a count */
3589+
if (count == 0 && withvalues)
3590+
count = 1;
3591+
35843592
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, 1 + (count != 0) + withvalues, "HRANDFIELD");
35853593
redis_cmd_append_sstr_key(&cmdstr, key, key_len, redis_sock, slot);
35863594

‎redis_legacy_arginfo.h

+1-1
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: 04fe88bbcc4d3dc3be06385e8931dfb080442f23 */
2+
* Stub hash: 70b942571cb2e3ef0b2531492840d9207f693b00 */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
55
ZEND_ARG_INFO(0, options)

‎tests/RedisTest.php

+10
Original file line numberDiff line numberDiff line change
@@ -3255,6 +3255,16 @@ public function testHRandField() {
32553255
$result = $this->redis->hRandField('key', ['count' => 2, 'withvalues' => true]);
32563256
$this->assertEquals(2, count($result));
32573257
$this->assertEquals(array_intersect_key($result, ['a' => 0, 'b' => 1, 'c' => 'foo', 'd' => 'bar', 'e' => null]), $result);
3258+
3259+
/* Make sure PhpRedis sends COUNt (1) when `WITHVALUES` is set */
3260+
$result = $this->redis->hRandField('key', ['withvalues' => true]);
3261+
$this->assertNull($this->redis->getLastError());
3262+
$this->assertIsArray($result);
3263+
$this->assertEquals(1, count($result));
3264+
3265+
/* We can return false if the key doesn't exist */
3266+
$this->assertIsInt($this->redis->del('notahash'));
3267+
$this->assertFalse($this->redis->hRandField('notahash'));
32583268
}
32593269

32603270
public function testSetRange() {

0 commit comments

Comments
 (0)