mirror of
https://github.com/predis/predis.git
synced 2026-08-24 17:39:36 +00:00
New commands: BITOP, BITCOUNT (Redis v2.6-dev).
This commit is contained in:
@@ -67,6 +67,24 @@ class PrefixHelpers
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified prefix to all the arguments but the first one.
|
||||
*
|
||||
* @param ICommand $command Command instance.
|
||||
* @param string $prefix Prefix string.
|
||||
*/
|
||||
public static function skipFirst(ICommand $command, $prefix)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
$length = count($arguments);
|
||||
|
||||
for ($i = 1; $i < $length; $i++) {
|
||||
$arguments[$i] = "$prefix{$arguments[$i]}";
|
||||
}
|
||||
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified prefix to all the arguments but the last one.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/bitop
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringBitOp extends Command implements IPrefixable
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'BITOP';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
if (count($arguments) === 3 && is_array($arguments[2])) {
|
||||
list($operation, $destination, ) = $arguments;
|
||||
$arguments = $arguments[2];
|
||||
array_unshift($arguments, $operation, $destination);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::skipFirst($this, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return $this->checkSameHashForKeys(
|
||||
array_slice(($args = $this->getArguments()), 1, count($args))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -409,6 +409,7 @@ class MasterSlaveReplication implements IConnectionReplication
|
||||
'ECHO' => true,
|
||||
'QUIT' => true,
|
||||
'OBJECT' => true,
|
||||
'BITCOUNT' => true,
|
||||
'SORT' => array($this, 'isSortReadOnly'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -217,6 +217,8 @@ class ServerVersion26 extends ServerProfile
|
||||
/* commands operating on string values */
|
||||
'psetex' => 'Predis\Commands\StringPreciseSetExpire',
|
||||
'incrbyfloat' => 'Predis\Commands\StringIncrementByFloat',
|
||||
'bitop' => 'Predis\Commands\StringBitOp',
|
||||
'bitcount' => 'Predis\Commands\StringBitCount',
|
||||
|
||||
/* commands operating on hashes */
|
||||
'hincrbyfloat' => 'Predis\Commands\HashIncrementByFloat',
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
<?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\Commands;
|
||||
|
||||
use \PHPUnit_Framework_TestCase as StandardTestCase;
|
||||
|
||||
/**
|
||||
* @group commands
|
||||
* @group realm-string
|
||||
*/
|
||||
class StringBitOpTest extends CommandTestCase
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCommand()
|
||||
{
|
||||
return 'Predis\Commands\StringBitOp';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedId()
|
||||
{
|
||||
return 'BITOP';
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testFilterArguments()
|
||||
{
|
||||
$arguments = array('AND', 'key:dst', 'key:01', 'key:02');
|
||||
$expected = array('AND', 'key:dst', 'key:01', 'key:02');
|
||||
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($arguments);
|
||||
|
||||
$this->assertSame($expected, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testFilterArgumentsKeysAsSingleArray()
|
||||
{
|
||||
$arguments = array('AND', 'key:dst', array('key:01', 'key:02'));
|
||||
$expected = array('AND', 'key:dst', 'key:01', 'key:02');
|
||||
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($arguments);
|
||||
|
||||
$this->assertSame($expected, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testParseResponse()
|
||||
{
|
||||
$raw = 10;
|
||||
$expected = 10;
|
||||
|
||||
$command = $this->getCommand();
|
||||
|
||||
$this->assertSame($expected, $command->parseResponse($raw));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testPrefixKeys()
|
||||
{
|
||||
$arguments = array('AND', 'key:dst', 'key:01', 'key:02');
|
||||
$expected = array('AND', 'prefix:key:dst', 'prefix:key:01', 'prefix:key:02');
|
||||
|
||||
$command = $this->getCommandWithArgumentsArray($arguments);
|
||||
$command->prefixKeys('prefix:');
|
||||
|
||||
$this->assertSame($expected, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
*/
|
||||
public function testCanPerformBitwiseAND()
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$redis->set('key:src:1', "h\x80");
|
||||
$redis->set('key:src:2', "R");
|
||||
|
||||
$this->assertSame(2, $redis->bitop('AND', 'key:dst', 'key:src:1', 'key:src:2'));
|
||||
$this->assertSame("@\x00", $redis->get('key:dst'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
*/
|
||||
public function testCanPerformBitwiseOR()
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$redis->set('key:src:1', "h\x80");
|
||||
$redis->set('key:src:2', "R");
|
||||
|
||||
$this->assertSame(2, $redis->bitop('OR', 'key:dst', 'key:src:1', 'key:src:2'));
|
||||
$this->assertSame("z\x80", $redis->get('key:dst'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
*/
|
||||
public function testCanPerformBitwiseXOR()
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$redis->set('key:src:1', "h\x80");
|
||||
$redis->set('key:src:2', "R");
|
||||
|
||||
$this->assertSame(2, $redis->bitop('XOR', 'key:dst', 'key:src:1', 'key:src:2'));
|
||||
$this->assertSame(":\x80", $redis->get('key:dst'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
*/
|
||||
public function testCanPerformBitwiseNOT()
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$redis->set('key:src:1', "h\x80");
|
||||
|
||||
$this->assertSame(2, $redis->bitop('NOT', 'key:dst', 'key:src:1'));
|
||||
$this->assertSame("\x97\x7f", $redis->get('key:dst'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @expectedException Predis\ServerException
|
||||
* @expectedExceptionMessage ERR BITOP NOT must be called with a single source key.
|
||||
*/
|
||||
public function testBitwiseNOTAcceptsOnlyOneSourceKey()
|
||||
{
|
||||
$this->getClient()->bitop('NOT', 'key:dst', 'key:src:1', 'key:src:2');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @expectedException Predis\ServerException
|
||||
* @expectedExceptionMessage ERR syntax error
|
||||
*/
|
||||
public function testThrowsExceptionOnInvalidOperation()
|
||||
{
|
||||
$this->getClient()->bitop('NOOP', 'key:dst', 'key:src:1', 'key:src:2');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @expectedException Predis\ServerException
|
||||
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
|
||||
*/
|
||||
public function testThrowsExceptionOnInvalidSourceKey()
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$redis->lpush('key:src:1', 'list');
|
||||
$redis->bitop('AND', 'key:dst', 'key:src:1', 'key:src:2');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
*/
|
||||
public function testDoesNotThrowExceptionOnInvalidDestinationKey()
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$redis->lpush('key:dst', 'list');
|
||||
$redis->bitop('AND', 'key:dst', 'key:src:1', 'key:src:2');
|
||||
|
||||
$this->assertSame('none', $redis->type('key:dst'));
|
||||
}
|
||||
}
|
||||
@@ -164,11 +164,13 @@ class ServerVersion26Test extends ServerVersionTestCase
|
||||
123 => 'pexpireat',
|
||||
124 => 'psetex',
|
||||
125 => 'incrbyfloat',
|
||||
126 => 'hincrbyfloat',
|
||||
127 => 'eval',
|
||||
128 => 'evalsha',
|
||||
129 => 'script',
|
||||
130 => 'time',
|
||||
126 => 'bitop',
|
||||
127 => 'bitcount',
|
||||
128 => 'hincrbyfloat',
|
||||
129 => 'eval',
|
||||
130 => 'evalsha',
|
||||
131 => 'script',
|
||||
132 => 'time',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,11 +164,13 @@ class ServerVersionNextTest extends ServerVersionTestCase
|
||||
123 => 'pexpireat',
|
||||
124 => 'psetex',
|
||||
125 => 'incrbyfloat',
|
||||
126 => 'hincrbyfloat',
|
||||
127 => 'eval',
|
||||
128 => 'evalsha',
|
||||
129 => 'script',
|
||||
130 => 'time',
|
||||
126 => 'bitop',
|
||||
127 => 'bitcount',
|
||||
128 => 'hincrbyfloat',
|
||||
129 => 'eval',
|
||||
130 => 'evalsha',
|
||||
131 => 'script',
|
||||
132 => 'time',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user