diff --git a/src/Cluster/ClusterStrategy.php b/src/Cluster/ClusterStrategy.php index 4d49f43f..fee7d2ff 100644 --- a/src/Cluster/ClusterStrategy.php +++ b/src/Cluster/ClusterStrategy.php @@ -138,6 +138,7 @@ abstract class ClusterStrategy implements StrategyInterface 'ZLEXCOUNT' => $getKeyFromFirstArgument, 'ZRANGEBYLEX' => $getKeyFromFirstArgument, 'ZREMRANGEBYLEX' => $getKeyFromFirstArgument, + 'ZREVRANGEBYLEX' => $getKeyFromFirstArgument, /* commands operating on hashes */ 'HDEL' => $getKeyFromFirstArgument, diff --git a/src/Command/Processor/KeyPrefixProcessor.php b/src/Command/Processor/KeyPrefixProcessor.php index b873ab42..b2d203da 100644 --- a/src/Command/Processor/KeyPrefixProcessor.php +++ b/src/Command/Processor/KeyPrefixProcessor.php @@ -155,6 +155,7 @@ class KeyPrefixProcessor implements ProcessorInterface 'ZLEXCOUNT' => 'self::first', 'ZRANGEBYLEX' => 'self::first', 'ZREMRANGEBYLEX' => 'self::first', + 'ZREVRANGEBYLEX' => 'self::first', ); } diff --git a/src/Command/ZSetReverseRangeByLex.php b/src/Command/ZSetReverseRangeByLex.php new file mode 100644 index 00000000..b9eb2512 --- /dev/null +++ b/src/Command/ZSetReverseRangeByLex.php @@ -0,0 +1,21 @@ + 'Predis\Command\ZSetLexCount', 'ZRANGEBYLEX' => 'Predis\Command\ZSetRangeByLex', 'ZREMRANGEBYLEX' => 'Predis\Command\ZSetRemoveRangeByLex', + 'ZREVRANGEBYLEX' => 'Predis\Command\ZSetReverseRangeByLex', /* commands operating on hashes */ 'HSCAN' => 'Predis\Command\HashScan', diff --git a/src/Profile/RedisVersion300.php b/src/Profile/RedisVersion300.php index 14bb6297..97578955 100644 --- a/src/Profile/RedisVersion300.php +++ b/src/Profile/RedisVersion300.php @@ -246,6 +246,7 @@ class RedisVersion300 extends RedisProfile 'ZLEXCOUNT' => 'Predis\Command\ZSetLexCount', 'ZRANGEBYLEX' => 'Predis\Command\ZSetRangeByLex', 'ZREMRANGEBYLEX' => 'Predis\Command\ZSetRemoveRangeByLex', + 'ZREVRANGEBYLEX' => 'Predis\Command\ZSetReverseRangeByLex', /* commands operating on hashes */ 'HSCAN' => 'Predis\Command\HashScan', diff --git a/src/Replication/ReplicationStrategy.php b/src/Replication/ReplicationStrategy.php index 169cd8c0..87f1d267 100644 --- a/src/Replication/ReplicationStrategy.php +++ b/src/Replication/ReplicationStrategy.php @@ -211,6 +211,7 @@ class ReplicationStrategy 'ZSCAN' => true, 'ZLEXCOUNT' => true, 'ZRANGEBYLEX' => true, + 'ZREVRANGEBYLEX' => true, 'HGET' => true, 'HMGET' => true, 'HEXISTS' => true, diff --git a/tests/Predis/Cluster/PredisStrategyTest.php b/tests/Predis/Cluster/PredisStrategyTest.php index 42d4db70..11c8b3d2 100644 --- a/tests/Predis/Cluster/PredisStrategyTest.php +++ b/tests/Predis/Cluster/PredisStrategyTest.php @@ -349,6 +349,7 @@ class PredisStrategyTest extends PredisTestCase 'ZLEXCOUNT' => 'keys-first', 'ZRANGEBYLEX' => 'keys-first', 'ZREMRANGEBYLEX' => 'keys-first', + 'ZREVRANGEBYLEX' => 'keys-first', /* commands operating on hashes */ 'HDEL' => 'keys-first', diff --git a/tests/Predis/Cluster/RedisStrategyTest.php b/tests/Predis/Cluster/RedisStrategyTest.php index 6a034edd..d15c84e8 100644 --- a/tests/Predis/Cluster/RedisStrategyTest.php +++ b/tests/Predis/Cluster/RedisStrategyTest.php @@ -359,6 +359,7 @@ class RedisStrategyTest extends PredisTestCase 'ZLEXCOUNT' => 'keys-first', 'ZRANGEBYLEX' => 'keys-first', 'ZREMRANGEBYLEX' => 'keys-first', + 'ZREVRANGEBYLEX' => 'keys-first', /* commands operating on hashes */ 'HDEL' => 'keys-first', diff --git a/tests/Predis/Command/Processor/KeyPrefixProcessorTest.php b/tests/Predis/Command/Processor/KeyPrefixProcessorTest.php index 709e6007..58208d64 100644 --- a/tests/Predis/Command/Processor/KeyPrefixProcessorTest.php +++ b/tests/Predis/Command/Processor/KeyPrefixProcessorTest.php @@ -825,6 +825,10 @@ class KeyPrefixProcessorTest extends PredisTestCase array('key', '-', '+'), array('prefix:key', '-', '+'), ), + array('ZREVRANGEBYLEX', + array('key', '+', '-', 'LIMIT', '0', '10'), + array('prefix:key', '+', '-', 'LIMIT', '0', '10'), + ), ); } } diff --git a/tests/Predis/Command/ZSetReverseRangeByLexTest.php b/tests/Predis/Command/ZSetReverseRangeByLexTest.php new file mode 100644 index 00000000..5bbf2ec8 --- /dev/null +++ b/tests/Predis/Command/ZSetReverseRangeByLexTest.php @@ -0,0 +1,192 @@ + array(0, 100), + ); + + $arguments = array('zset', '[a', '[z', $modifiers); + $expected = array('zset', '[a', '[z', 'LIMIT', 0, 100); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsWithNamedLimit() + { + $arguments = array('zset', '[a', '[z', array('limit' => array('offset' => 1, 'count' => 2))); + $expected = array('zset', '[a', '[z', 'LIMIT', 1, 2); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('a', 'b', 'c'); + $expected = array('a', 'b', 'c'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group connected + * @requiresRedisVersion >= 2.8.9 + */ + public function testReturnsElementsInWholeRange() + { + $redis = $this->getClient(); + + $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g'); + + $this->assertSame(array('g', 'f', 'e', 'd', 'c', 'b', 'a'), $redis->zrevrangebylex('letters', '+', '-')); + $this->assertSame(array(), $redis->zrevrangebylex('letters', '-', '+')); + $this->assertSame(array(), $redis->zrevrangebylex('unknown', '-', '+')); + $this->assertSame(array(), $redis->zrevrangebylex('unknown', '+', '-')); + } + + /** + * @group connected + * @requiresRedisVersion >= 2.8.9 + */ + public function testReturnsElementsInInclusiveRange() + { + $redis = $this->getClient(); + + $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g'); + + $this->assertSame(array('a'), $redis->zrevrangebylex('letters', '[a', '[a')); + $this->assertSame(array('f', 'e', 'd', 'c'), $redis->zrevrangebylex('letters', '[f', '[c')); + $this->assertSame(array('g', 'f', 'e'), $redis->zrevrangebylex('letters', '+', '[e')); + $this->assertSame(array(), $redis->zrevrangebylex('letters', '-', '[c')); + $this->assertSame(array(), $redis->zrevrangebylex('letters', '[z', '[x')); + $this->assertSame(array(), $redis->zrevrangebylex('unknown', '[1', '[0')); + } + + /** + * @group connected + * @requiresRedisVersion >= 2.8.9 + */ + public function testReturnsElementsInExclusiveRange() + { + $redis = $this->getClient(); + + $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g'); + + $this->assertSame(array(), $redis->zrevrangebylex('letters', '(a', '(a')); + $this->assertSame(array('e', 'd'), $redis->zrevrangebylex('letters', '(f', '(c')); + $this->assertSame(array('g', 'f'), $redis->zrevrangebylex('letters', '+', '(e')); + $this->assertSame(array(), $redis->zrevrangebylex('letters', '-', '(c')); + $this->assertSame(array(), $redis->zrevrangebylex('letters', '(z', '(x')); + $this->assertSame(array(), $redis->zrevrangebylex('unknown', '(1', '(0')); + } + + /** + * @group connected + * @requiresRedisVersion >= 2.8.9 + */ + public function testReturnsElementsInMixedRange() + { + $redis = $this->getClient(); + + $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g'); + + $this->assertSame(array(), $redis->zrevrangebylex('letters', '[a', '(a')); + $this->assertSame(array(), $redis->zrevrangebylex('letters', '(a', '[a')); + $this->assertSame(array('f', 'e', 'd'), $redis->zrevrangebylex('letters', '[f', '(c')); + $this->assertSame(array('e', 'd', 'c'), $redis->zrevrangebylex('letters', '(f', '[c')); + $this->assertSame(array(), $redis->zrevrangebylex('unknown', '[5', '(0')); + } + + /** + * @group connected + * @requiresRedisVersion >= 2.8.9 + */ + public function testRangeWithLimitModifier() + { + $redis = $this->getClient(); + + $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g'); + + $this->assertSame(array('e', 'd', 'c'), $redis->zrevrangebylex('letters', '+', '-', 'LIMIT', '2', '3')); + $this->assertSame(array('e', 'd', 'c'), $redis->zrevrangebylex('letters', '+', '-', array('limit' => array(2, 3)))); + $this->assertSame(array('e', 'd', 'c'), $redis->zrevrangebylex('letters', '+', '-', array('limit' => array('offset' => 2, 'count' => 3)))); + $this->assertSame(array(), $redis->zrevrangebylex('letters', '[f', '[a', 'LIMIT', '2', '0')); + $this->assertSame(array(), $redis->zrevrangebylex('letters', '[f', '[a', 'LIMIT', '-4', '2')); + } + + /** + * @group connected + * @requiresRedisVersion >= 2.8.9 + * @expectedException \Predis\Response\ServerException + * @expectedExceptionMessage min or max not valid string range item + */ + public function testThrowsExceptionOnInvalidRangeFormat() + { + $redis = $this->getClient(); + + $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g'); + $redis->zrevrangebylex('letters', 'f', 'b'); + } + + /** + * @group connected + * @requiresRedisVersion >= 2.8.9 + * @expectedException \Predis\Response\ServerException + * @expectedExceptionMessage Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zrevrangebylex('foo', '+', '-'); + } +} diff --git a/tests/Predis/Profile/RedisUnstableTest.php b/tests/Predis/Profile/RedisUnstableTest.php index 21dde616..adeea30c 100644 --- a/tests/Predis/Profile/RedisUnstableTest.php +++ b/tests/Predis/Profile/RedisUnstableTest.php @@ -181,12 +181,13 @@ class RedisUnstableTest extends PredisProfileTestCase 140 => 'ZLEXCOUNT', 141 => 'ZRANGEBYLEX', 142 => 'ZREMRANGEBYLEX', - 143 => 'HSCAN', - 144 => 'PUBSUB', - 145 => 'PFADD', - 146 => 'PFCOUNT', - 147 => 'PFMERGE', - 148 => 'COMMAND', + 143 => 'ZREVRANGEBYLEX', + 144 => 'HSCAN', + 145 => 'PUBSUB', + 146 => 'PFADD', + 147 => 'PFCOUNT', + 148 => 'PFMERGE', + 149 => 'COMMAND', ); } } diff --git a/tests/Predis/Profile/RedisVersion280Test.php b/tests/Predis/Profile/RedisVersion280Test.php index 11ab7d6e..b72d7433 100644 --- a/tests/Predis/Profile/RedisVersion280Test.php +++ b/tests/Predis/Profile/RedisVersion280Test.php @@ -181,12 +181,13 @@ class RedisVersion280Test extends PredisProfileTestCase 140 => 'ZLEXCOUNT', 141 => 'ZRANGEBYLEX', 142 => 'ZREMRANGEBYLEX', - 143 => 'HSCAN', - 144 => 'PUBSUB', - 145 => 'PFADD', - 146 => 'PFCOUNT', - 147 => 'PFMERGE', - 148 => 'COMMAND', + 143 => 'ZREVRANGEBYLEX', + 144 => 'HSCAN', + 145 => 'PUBSUB', + 146 => 'PFADD', + 147 => 'PFCOUNT', + 148 => 'PFMERGE', + 149 => 'COMMAND', ); } } diff --git a/tests/Predis/Profile/RedisVersion300Test.php b/tests/Predis/Profile/RedisVersion300Test.php index c7fc4b73..088051ab 100644 --- a/tests/Predis/Profile/RedisVersion300Test.php +++ b/tests/Predis/Profile/RedisVersion300Test.php @@ -181,12 +181,13 @@ class RedisVersion300Test extends PredisProfileTestCase 140 => 'ZLEXCOUNT', 141 => 'ZRANGEBYLEX', 142 => 'ZREMRANGEBYLEX', - 143 => 'HSCAN', - 144 => 'PUBSUB', - 145 => 'PFADD', - 146 => 'PFCOUNT', - 147 => 'PFMERGE', - 148 => 'COMMAND', + 143 => 'ZREVRANGEBYLEX', + 144 => 'HSCAN', + 145 => 'PUBSUB', + 146 => 'PFADD', + 147 => 'PFCOUNT', + 148 => 'PFMERGE', + 149 => 'COMMAND', ); } } diff --git a/tests/Predis/Replication/ReplicationStrategyTest.php b/tests/Predis/Replication/ReplicationStrategyTest.php index befa082e..6735b4c0 100644 --- a/tests/Predis/Replication/ReplicationStrategyTest.php +++ b/tests/Predis/Replication/ReplicationStrategyTest.php @@ -346,6 +346,7 @@ class ReplicationStrategyTest extends PredisTestCase 'ZLEXCOUNT' => 'read', 'ZRANGEBYLEX' => 'read', 'ZREMRANGEBYLEX' => 'write', + 'ZREVRANGEBYLEX' => 'read', /* commands operating on hashes */ 'HDEL' => 'write',