8000 Merge branch 'srandmember_count' · jrtkcoder/phpredis@242a16d · GitHub
[go: up one dir, main page]

Skip to content

Commit 242a16d

Browse files
Merge branch 'srandmember_count'
Conflicts: tests/TestRedis.php
2 parents f702e88 + 71a002d commit 242a16d

File tree

3 files changed

+119
-7
lines changed
8000

3 files changed

+119
-7
lines changed

README.markdown

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2207,17 +2207,29 @@ $redis->sPop('key1'); /* 'member3', 'key1' => {'member2'} */
22072207
-----
22082208
_**Description**_: Returns a random element from the set value at Key, without removing it.
22092209
##### *Parameters*
2210-
*key*
2210+
*key*
2211+
*count* (Integer, optional)
22112212
##### *Return value*
2212-
*String* value from the set
2213+
If no count is provided, a random *String* value from the set will be returned. If a count
2214+
is provided, an array of values from the set will be returned. Read about the different
2215+
ways to use the count here: [SRANDMEMBER](http://redis.io/commands/srandmember)
22132216
*Bool* `FALSE` if set identified by key is empty or doesn't exist.
22142217
##### *Example*
22152218
~~~
22162219
$redis->sAdd('key1' , 'member1');
22172220
$redis->sAdd('key1' , 'member2');
22182221
$redis->sAdd('key1' , 'member3'); /* 'key1' => {'member3', 'member1', 'member2'}*/
2222+
2223+
// No count
22192224
$redis->sRandMember('key1'); /* 'member1', 'key1' => {'member3', 'member1', 'member2'} */
22202225
$redis->sRandMember('key1'); /* 'member3', 'key1' => {'member3', 'member1', 'member2'} */
2226+
2227+
// With a count
2228+
$redis->sRandMember('key1', 3); // Will return an array with all members from the set
2229+
$redis->sRandMember('key1', 2); // Will an array with 2 members of the set
2230+
$redis->sRandMember('key1', -100); // Will return an array of 100 elements, picked from our set (with dups)
2231+
$redis->sRandMember('empty-set', 100); // Will return an empty array
2232+
$redis->sRandMember('not-a-set', 100); // Will return FALSE
22212233
~~~
22222234

22232235
### sRem, sRemove

redis.c

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,19 +2195,62 @@ PHP_METHOD(Redis, sPop)
21952195
/* }}} */
21962196

21972197
/* }}} */
2198-
/* {{{ proto string Redis::sRandMember(string key)
2198+
/* {{{ proto string Redis::sRandMember(string key [int count])
21992199
*/
22002200
PHP_METHOD(Redis, sRandMember)
22012201
{
2202-
generic_pop_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "SRANDMEMBER", 11);
2202+
zval *object;
2203+
RedisSock *redis_sock;
2204+
char *key = NULL, *cmd;
2205+
int key_len, cmd_len, key_free = 0;
2206+
long count;
2207+
2208+
// Parse our params
2209+
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|l",
2210+
&object, redis_ce, &key, &key_len, &count) == FAILURE) {
2211+
RETURN_FALSE;
2212+
}
2213+
2214+
// Get our redis socket
2215+
if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) {
2216+
RETURN_FALSE;
2217+
}
2218+
2219+
// Prefix our key if necissary
2220+
key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC);
2221+
2222+
// If we have two arguments, we're running with an optional COUNT, which will return
2223+
// a multibulk reply. Without the argument we'll return a string response
2224+
if(ZEND_NUM_ARGS() == 2) {
2225+
// Construct our command with count
2226+
cmd_len = redis_cmd_format_static(&cmd, "SRANDMEMBER", "sl", key, key_len, count);
2227+
} else {
2228+
// Construct our command
2229+
cmd_len = redis_cmd_format_static(&cmd, "SRANDMEMBER", "s", key, key_len);
2230+
}
2231+
2232+
// Free our key if we prefixed it
2233+
if(key_free) efree(key);
2234+
2235+
// Process our command
2236+
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
2237+
2238+
// Process our reply
2239+
IF_ATOMIC() {
2240+
// This will be bulk or multi-bulk depending if we passed the optional [COUNT] argument
2241+
if(redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL) < 0) {
2242+
RETURN_FALSE;
2243+
}
2244+
}
2245+
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
22032246
}
22042247
/* }}} */
22052248

22062249
/* {{{ proto boolean Redis::sContains(string set, string value)
22072250
*/
22082251
PHP_METHOD(Redis, sContains)
22092252
{
2210-
zval *object;
2253+
zval *object;
22112254
RedisSock *redis_sock;
22122255
char *key = NULL, *val = NULL, *cmd;
22132256
int key_len, val_len, cmd_len;

tests/TestRedis.php

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,61 @@ public function testsRandMember() {
10831083
}
10841084
}
10851085

1086+
public function testSRandMemberWithCount() {
1087+
// Make sure the set is nuked
1088+
$this->redis->delete('set0');
1089+
1090+
// Run with a count (positive and negative) on an empty set
1091+
$ret_pos = $this->redis->sRandMember('set0', 10);
1092+
$ret_neg = $this->redis->sRandMember('set0', -10);
1093+
1094+
// Should both be empty arrays
1095+
$this->assertTrue(is_array($ret_pos) && empty($ret_pos));
1096+
$this->assertTrue(is_array($ret_neg) && empty($ret_neg));
1097+
1098+
// Add a few items to the set
1099+
for($i=0;$i<100;$i++) {
1100+
$this->redis->sadd('set0', "member$i");
1101+
}
1102+
1103+
// Get less than the size of the list
1104+
$ret_slice = $this->redis->srandmember('set0', 20);
1105+
1106+
// Should be an array with 20 items
1107+
$this->assertTrue(is_array($ret_slice) && count($ret_slice) == 20);
1108+
1109+
// Ask for more items than are in the list (but with a positive count)
1110+
$ret_slice = $this->redis->srandmember('set0', 200);
1111+
1112+
// Should be an array, should be however big the set is, exactly
1113+
$this->assertTrue(is_array($ret_slice) && count($ret_slice) == $i);
1114+
1115+
// Now ask for too many items but negative
1116+
$ret_slice = $this->redis->srandmember('set0', -200);
1117+
1118+
// Should be an array, should have exactly the # of items we asked for (will be dups)
1119+
$this->assertTrue(is_array($ret_slice) && count($ret_slice) == 200);
1120+
1121+
//
1122+
// Test in a pipeline
1123+
//
1124+
1125+
$pipe = $this->redis->pipeline();
1126+
1127+
$pipe->srandmember('set0', 20);
1128+
$pipe->srandmember('set0', 200);
1129+
$pipe->srandmember('set0', -200);
1130+
1131+
$ret = $this->redis->exec();
1132+
1133+
$this->assertTrue(is_array($ret[0]) && count($ret[0]) == 20);
1134+
$this->assertTrue(is_array($ret[1]) && count($ret[1]) == $i);
1135+
$this->assertTrue(is_array($ret[2]) && count($ret[2]) == 200);
1136+
1137+
// Kill the set
1138+
$this->redis->del('set0');
1139+
}
1140+
10861141
public function testsContains()
10871142
{
10881143
$this->redis->delete('set');
@@ -3263,8 +3318,10 @@ public function testUnserialize() {
32633318
1,1.5,'one',Array('this','is','an','array')
32643319
);
32653320

3266-
$serializers = Array(Redis::SERIALIZER_PHP);
3267-
if(defined('Redis::SERIALIZER_IGBINARY')) $serializers[] = Redis::SERIALIZER_IGBINARY;
3321+
$serializers = Array(Redis::SERIALIZER_PHP);
3322+
if(defined('Redis::SERIALIZER_IGBINARY')) {
3323+
$serializers[] = Redis::SERIALIZER_IGBINARY;
3324+
}
32683325

32693326
foreach($serializers as $mode) {
32703327
$vals_enc = Array();

0 commit comments

Comments
 (0)
0