New command: ZRANGEBYLEX (Redis 2.8.9).

This commit is contained in:
Daniele Alessandri
2014-06-09 12:23:26 +02:00
parent 8dbac3dd73
commit ea32f74512
13 changed files with 279 additions and 10 deletions
+1
View File
@@ -140,6 +140,7 @@ class PredisStrategy implements StrategyInterface
'ZUNIONSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
'ZSCAN' => $keyIsFirstArgument,
'ZLEXCOUNT' => $keyIsFirstArgument,
'ZRANGEBYLEX' => $keyIsFirstArgument,
/* commands operating on hashes */
'HDEL' => $keyIsFirstArgument,
+1
View File
@@ -125,6 +125,7 @@ class RedisStrategy implements StrategyInterface
'ZSCORE' => $keyIsFirstArgument,
'ZSCAN' => $keyIsFirstArgument,
'ZLEXCOUNT' => $keyIsFirstArgument,
'ZRANGEBYLEX' => $keyIsFirstArgument,
/* commands operating on hashes */
'HDEL' => $keyIsFirstArgument,
@@ -153,6 +153,7 @@ class KeyPrefixProcessor implements ProcessorInterface
'PFCOUNT' => 'self::all',
'PFMERGE' => 'self::all',
'ZLEXCOUNT' => 'self::first',
'ZRANGEBYLEX' => 'self::first',
);
}
+54
View File
@@ -0,0 +1,54 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/zrangebylex
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ZSetRangeByLex extends ZSetRange
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'ZRANGEBYLEX';
}
/**
* {@inheritdoc}
*/
protected function prepareOptions($options)
{
$opts = array_change_key_case($options, CASE_UPPER);
$finalizedOpts = array();
if (isset($opts['LIMIT']) && is_array($opts['LIMIT'])) {
$limit = array_change_key_case($opts['LIMIT'], CASE_UPPER);
$finalizedOpts[] = 'LIMIT';
$finalizedOpts[] = isset($limit['OFFSET']) ? $limit['OFFSET'] : $limit[0];
$finalizedOpts[] = isset($limit['COUNT']) ? $limit['COUNT'] : $limit[1];
}
return $finalizedOpts;
}
/**
* {@inheritdoc}
*/
protected function withScores()
{
return false;
}
}
+1
View File
@@ -241,6 +241,7 @@ class RedisVersion280 extends RedisProfile
/* commands operating on sorted sets */
'ZSCAN' => 'Predis\Command\ZSetScan',
'ZLEXCOUNT' => 'Predis\Command\ZSetLexCount',
'ZRANGEBYLEX' => 'Predis\Command\ZSetRangeByLex',
/* commands operating on hashes */
'HSCAN' => 'Predis\Command\HashScan',
@@ -205,6 +205,7 @@ class ReplicationStrategy
'ZREVRANK' => true,
'ZSCAN' => true,
'ZLEXCOUNT' => true,
'ZRANGEBYLEX' => true,
'HGET' => true,
'HMGET' => true,
'HEXISTS' => true,
@@ -346,6 +346,7 @@ class PredisStrategyTest extends PredisTestCase
'ZUNIONSTORE' => 'keys-zaggregated',
'ZSCAN' => 'keys-first',
'ZLEXCOUNT' => 'keys-first',
'ZRANGEBYLEX' => 'keys-first',
/* commands operating on hashes */
'HDEL' => 'keys-first',
@@ -343,6 +343,7 @@ class RedisStrategyTest extends PredisTestCase
'ZSCORE' => 'keys-first',
'ZSCAN' => 'keys-first',
'ZLEXCOUNT' => 'keys-first',
'ZRANGEBYLEX' => 'keys-first',
/* commands operating on hashes */
'HDEL' => 'keys-first',
@@ -815,6 +815,10 @@ class KeyPrefixProcessorTest extends PredisTestCase
array('key', '-', '+'),
array('prefix:key', '-', '+'),
),
array('ZRANGEBYLEX',
array('key', '-', '+', 'LIMIT', '0', '10'),
array('prefix:key', '-', '+', 'LIMIT', '0', '10'),
),
);
}
}
+201
View File
@@ -0,0 +1,201 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @group commands
* @group realm-zset
*/
class ZSetRangeByLexTest extends PredisCommandTestCase
{
/**
* {@inheritdoc}
*/
protected function getExpectedCommand()
{
return 'Predis\Command\ZSetRangeByLex';
}
/**
* {@inheritdoc}
*/
protected function getExpectedId()
{
return 'ZRANGEBYLEX';
}
/**
* @group disconnected
*/
public function testFilterArguments()
{
$modifiers = array(
'limit' => 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
*/
public function testReturnsElementsInWholeRange()
{
$this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
$redis = $this->getClient();
$redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
$this->assertSame(array('a', 'b', 'c', 'd', 'e', 'f', 'g'), $redis->zrangebylex('letters', '-', '+'));
$this->assertSame(array(), $redis->zrangebylex('letters', '+', '-'));
$this->assertSame(array(), $redis->zrangebylex('unknown', '-', '+'));
$this->assertSame(array(), $redis->zrangebylex('unknown', '+', '-'));
}
/**
* @group connected
*/
public function testReturnsElementsInInclusiveRange()
{
$this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
$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->zrangebylex('letters', '[a', '[a'));
$this->assertSame(array('c', 'd', 'e', 'f'), $redis->zrangebylex('letters', '[c', '[f'));
$this->assertSame(array('a', 'b', 'c'), $redis->zrangebylex('letters', '-', '[c'));
$this->assertSame(array(), $redis->zrangebylex('letters', '+', '[c'));
$this->assertSame(array(), $redis->zrangebylex('letters', '[x', '[z'));
$this->assertSame(array(), $redis->zrangebylex('unknown', '[0', '[1'));
}
/**
* @group connected
*/
public function testReturnsElementsInExclusiveRange()
{
$this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
$redis = $this->getClient();
$redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
$this->assertSame(array(), $redis->zrangebylex('letters', '(a', '(a'));
$this->assertSame(array('d', 'e'), $redis->zrangebylex('letters', '(c', '(f'));
$this->assertSame(array('a', 'b'), $redis->zrangebylex('letters', '-', '(c'));
$this->assertSame(array(), $redis->zrangebylex('letters', '+', '(c'));
$this->assertSame(array(), $redis->zrangebylex('letters', '(x', '(z'));
$this->assertSame(array(), $redis->zrangebylex('unknown', '(0', '(1'));
}
/**
* @group connected
*/
public function testReturnsElementsInMixedRange()
{
$this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
$redis = $this->getClient();
$redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
$this->assertSame(array(), $redis->zrangebylex('letters', '[a', '(a'));
$this->assertSame(array(), $redis->zrangebylex('letters', '(a', '[a'));
$this->assertSame(array('c', 'd', 'e'), $redis->zrangebylex('letters', '[c', '(f'));
$this->assertSame(array('d', 'e', 'f'), $redis->zrangebylex('letters', '(c', '[f'));
$this->assertSame(array(), $redis->zrangebylex('unknown', '[0', '(5'));
}
/**
* @group connected
*/
public function testRangeWithLimitModifier()
{
$this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
$redis = $this->getClient();
$redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
$this->assertSame(array('c', 'd', 'e'), $redis->zrangebylex('letters', '-', '+', 'LIMIT', '2', '3'));
$this->assertSame(array('c', 'd', 'e'), $redis->zrangebylex('letters', '-', '+', array('limit' => array(2, 3))));
$this->assertSame(array('c', 'd', 'e'), $redis->zrangebylex('letters', '-', '+', array('limit' => array('offset' => 2, 'count' => 3))));
$this->assertSame(array(), $redis->zrangebylex('letters', '[a', '[f', 'LIMIT', '2', '0'));
$this->assertSame(array(), $redis->zrangebylex('letters', '[a', '[f', 'LIMIT', '-4', '2'));
}
/**
* @group connected
* @expectedException Predis\Response\ServerException
* @expectedExceptionMessage min or max not valid string range item
*/
public function testThrowsExceptionOnInvalidRangeFormat()
{
$this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
$redis = $this->getClient();
$redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
$redis->zrangebylex('letters', 'b', 'f');
}
/**
* @group connected
* @expectedException Predis\Response\ServerException
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
$this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
$redis = $this->getClient();
$redis->set('foo', 'bar');
$redis->zrangebylex('foo', '-', '+');
}
}
+6 -5
View File
@@ -178,11 +178,12 @@ class RedisUnstableTest extends PredisProfileTestCase
137 => 'SSCAN',
138 => 'ZSCAN',
139 => 'ZLEXCOUNT',
140 => 'HSCAN',
141 => 'PUBSUB',
142 => 'PFADD',
143 => 'PFCOUNT',
144 => 'PFMERGE',
140 => 'ZRANGEBYLEX',
141 => 'HSCAN',
142 => 'PUBSUB',
143 => 'PFADD',
144 => 'PFCOUNT',
145 => 'PFMERGE',
);
}
}
+6 -5
View File
@@ -178,11 +178,12 @@ class RedisVersion280Test extends PredisProfileTestCase
137 => 'SSCAN',
138 => 'ZSCAN',
139 => 'ZLEXCOUNT',
140 => 'HSCAN',
141 => 'PUBSUB',
142 => 'PFADD',
143 => 'PFCOUNT',
144 => 'PFMERGE',
140 => 'ZRANGEBYLEX',
141 => 'HSCAN',
142 => 'PUBSUB',
143 => 'PFADD',
144 => 'PFCOUNT',
145 => 'PFMERGE',
);
}
}
@@ -343,6 +343,7 @@ class ReplicationStrategyTest extends PredisTestCase
'ZSCORE' => 'read',
'ZSCAN' => 'read',
'ZLEXCOUNT' => 'read',
'ZRANGEBYLEX' => 'read',
/* commands operating on hashes */
'HDEL' => 'write',