diff --git a/CHANGELOG.md b/CHANGELOG.md index 385cef48..9eaddf88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ v0.7.3 (2012-xx-xx) =============================================================================== +- When the number of keys `Predis\Commands\ScriptedCommand` is negative, Predis + will count from the end of the arguments list to calculate the actual number + of keys that will be interpreted as elements for `KEYS` by the underlying + `EVAL` command. + - __FIX__: `examples\CustomDistributionStrategy.php` had a mistyped constructor call and produced a bad distribution due to an error as pointed in ISSUE #63. This bug is limited to the above mentioned example and does not affect the diff --git a/examples/ServerSideScripting.php b/examples/ServerSideScripting.php index d71e52da..f58eaced 100644 --- a/examples/ServerSideScripting.php +++ b/examples/ServerSideScripting.php @@ -20,30 +20,47 @@ require 'SharedConfigurations.php'; use Predis\Commands\ScriptedCommand; -class IncrementExistingKey extends ScriptedCommand +class IncrementExistingKeysBy extends ScriptedCommand { public function getKeysCount() { - return 1; + // Tell Predis to use all the arguments but the last one as arguments + // for KEYS. The last one will be used to populate ARGV. + return -1; } public function getScript() { return <<getProfile()->defineCommand('increx', 'IncrementExistingKey'); +$client->getProfile()->defineCommand('increxby', 'IncrementExistingKeysBy'); -$client->set('foo', 10); +$client->mset('foo', 10, 'foobar', 100); -var_dump($client->increx('foo')); // int(11) -var_dump($client->increx('bar')); // NULL +var_export($client->increxby('foo', 'foofoo', 'foobar', 50)); + +/* +array ( + 0 => 60, + 1 => NULL, + 2 => 150, +) +*/ diff --git a/lib/Predis/Commands/ScriptedCommand.php b/lib/Predis/Commands/ScriptedCommand.php index 7f702802..10cb12bf 100644 --- a/lib/Predis/Commands/ScriptedCommand.php +++ b/lib/Predis/Commands/ScriptedCommand.php @@ -60,8 +60,13 @@ abstract class ScriptedCommand extends ServerEval */ protected function filterArguments(Array $arguments) { - $header = array($this->getScript(), ($keys = $this->getKeysCount()) !== false ? $keys : count($arguments)); + if (false !== $numkeys = $this->getKeysCount()) { + $numkeys = $numkeys >= 0 ? $numkeys : count($arguments) + $numkeys; + } + else { + $numkeys = count($arguments); + } - return array_merge($header, $arguments); + return array_merge(array($this->getScript(), $numkeys), $arguments); } } diff --git a/tests/Predis/Commands/ScriptedCommandTest.php b/tests/Predis/Commands/ScriptedCommandTest.php index 48331eaa..ae5f6296 100644 --- a/tests/Predis/Commands/ScriptedCommandTest.php +++ b/tests/Predis/Commands/ScriptedCommandTest.php @@ -39,6 +39,25 @@ class ScriptedCommandTest extends StandardTestCase $this->assertSame(array_merge(array(self::LUA_SCRIPT, 2), $arguments), $command->getArguments()); } + /** + * @group disconnected + */ + public function testGetArgumentsWithNegativeKeysCount() + { + $arguments = array('key1', 'key2', 'value1', 'value2'); + + $command = $this->getMock('Predis\Commands\ScriptedCommand', array('getScript', 'getKeysCount')); + $command->expects($this->once()) + ->method('getScript') + ->will($this->returnValue(self::LUA_SCRIPT)); + $command->expects($this->once()) + ->method('getKeysCount') + ->will($this->returnValue(-2)); + $command->setArguments($arguments); + + $this->assertSame(array_merge(array(self::LUA_SCRIPT, 2), $arguments), $command->getArguments()); + } + /** * @group disconnected */ @@ -58,6 +77,25 @@ class ScriptedCommandTest extends StandardTestCase $this->assertSame(array('key1', 'key2'), $command->getKeys()); } + /** + * @group disconnected + */ + public function testGetKeysWithNegativeKeysCount() + { + $arguments = array('key1', 'key2', 'value1', 'value2'); + + $command = $this->getMock('Predis\Commands\ScriptedCommand', array('getScript', 'getKeysCount')); + $command->expects($this->once()) + ->method('getScript') + ->will($this->returnValue(self::LUA_SCRIPT)); + $command->expects($this->exactly(2)) + ->method('getKeysCount') + ->will($this->returnValue(-2)); + $command->setArguments($arguments); + + $this->assertSame(array('key1', 'key2'), $command->getKeys()); + } + /** * @group disconnected */ @@ -80,6 +118,28 @@ class ScriptedCommandTest extends StandardTestCase $this->assertSame($expected, $command->getKeys()); } + /** + * @group disconnected + */ + public function testPrefixKeysWithNegativeKeysCount() + { + $arguments = array('foo', 'hoge', 'bar', 'piyo'); + $expected = array('prefix:foo', 'prefix:hoge'); + + $command = $this->getMock('Predis\Commands\ScriptedCommand', array('getScript', 'getKeysCount')); + $command->expects($this->once()) + ->method('getScript') + ->will($this->returnValue(self::LUA_SCRIPT)); + $command->expects($this->exactly(2)) + ->method('getKeysCount') + ->will($this->returnValue(-2)); + $command->setArguments($arguments); + + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getKeys()); + } + /** * @group disconnected */