From e9d5e21980f13b9374b2de3983eb96a64f65677f Mon Sep 17 00:00:00 2001 From: michael-grunder Date: Thu, 9 May 2013 11:03:43 -0700 Subject: Support for '-inf', 'inf', and '+inf' for WEIGHTS Redis allows the use of these specialized numbers in the WEIGHTS argument for things like ZUNIONSTORE AND ZINTERSTORE --- redis.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/redis.c b/redis.c index 543ceecf..d85620de 100644 --- a/redis.c +++ b/redis.c @@ -4394,9 +4394,15 @@ PHPAPI void generic_z_command(INTERNAL_FUNCTION_PARAMETERS, char *command, int c zend_hash_get_current_data_ex(arr_weights_hash, (void**) &data, &pointer) == SUCCESS; zend_hash_move_forward_ex(arr_weights_hash, &pointer)) { - if (Z_TYPE_PP(data) != IS_LONG && Z_TYPE_PP(data) != IS_DOUBLE) { - continue; // ignore non-numeric arguments. - } + // Ignore non numeric arguments, unless they're the special Redis numbers + // "inf" ,"-inf", and "+inf" which can be passed as weights + if (Z_TYPE_PP(data) != IS_LONG && Z_TYPE_PP(data) != IS_DOUBLE && + strncasecmp(Z_STRVAL_PP(data), "inf", sizeof("inf")) != 0 && + strncasecmp(Z_STRVAL_PP(data), "-inf", sizeof("-inf")) != 0 && + strncasecmp(Z_STRVAL_PP(data), "+inf", sizeof("+inf")) != 0) + { + continue; + } old_cmd = NULL; if(*cmd) { @@ -4412,12 +4418,18 @@ PHPAPI void generic_z_command(INTERNAL_FUNCTION_PARAMETERS, char *command, int c , integer_length(Z_LVAL_PP(data)), Z_LVAL_PP(data)); } else if(Z_TYPE_PP(data) == IS_DOUBLE) { - cmd_len = redis_cmd_format(&cmd, "%s" /* cmd */ "$%f" _NL /* data, including size */ , cmd, cmd_len , Z_DVAL_PP(data)); + } else if(Z_TYPE_PP(data) == IS_STRING) { + cmd_len = redis_cmd_format(&cmd, + "%s" /* cmd */ + "$%d" _NL /* data len */ + "%s" _NL /* data */ + , cmd, cmd_len, Z_STRLEN_PP(data), + Z_STRVAL_PP(data), Z_STRLEN_PP(data)); } // keep track of elements added -- cgit v1.2.3 From 75ddd072a4f3180329c87669ca643d7b1bb142c7 Mon Sep 17 00:00:00 2001 From: michael-grunder Date: Thu, 9 May 2013 11:55:43 -0700 Subject: Add unit tests for -inf/inf/+inf WEIGHTS Addresses issue #336 --- tests/TestRedis.php | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/TestRedis.php b/tests/TestRedis.php index 20fdb358..70d38355 100644 --- a/tests/TestRedis.php +++ b/tests/TestRedis.php @@ -1974,11 +1974,33 @@ class Redis_Test extends TestSuite $this->assertTrue($this->redis->zunion('key3', array('key1', 'key2'), array(2, 3.0)) === 3); - $this->redis->delete('key1'); $this->redis->delete('key2'); $this->redis->delete('key3'); + // Test 'inf', '-inf', and '+inf' weights (GitHub issue #336) + $this->redis->zadd('key1', 1, 'one', 2, 'two', 3, 'three'); + $this->redis->zadd('key2', 3, 'three', 4, 'four', 5, 'five'); + + // Make sure phpredis handles these weights + $this->assertTrue($this->redis->zunion('key3', array('key1','key2'), array(1, 'inf')) === 5); + $this->assertTrue($this->redis->zunion('key3', array('key1','key2'), array(1, '-inf')) === 5); + $this->assertTrue($this->redis->zunion('key3', array('key1','key2'), array(1, '+inf')) === 5); + + // Now, confirm that they're being sent, and that it works + $arr_weights = Array('inf','-inf','+inf'); + + foreach($arr_weights as $str_weight) { + $r = $this->redis->zunionstore('key3', array('key1','key2'), array(1,$str_weight)); + $this->assertTrue($r===5); + $r = $this->redis->zrangebyscore('key3', '(-inf', '(inf',array('withscores'=>true)); + $this->assertTrue(count($r)===2); + $this->assertTrue(isset($r['one'])); + $this->assertTrue(isset($r['two'])); + } + + $this->redis->del('key1','key2','key3'); + $this->redis->zadd('key1', 2000.1, 'one'); $this->redis->zadd('key1', 3000.1, 'two'); $this->redis->zadd('key1', 4000.1, 'three'); -- cgit v1.2.3