Skip to content
Browse files

Scripting abstraction can use negatives to calculate number of keys.

With a negative number 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.
  • Loading branch information...
1 parent f4c58b9 commit 5af2b628f10b8be9eaa24d5bf64b83930c68e528 @nrk committed Apr 25, 2012
View
5 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
View
37 examples/ServerSideScripting.php
@@ -20,30 +20,47 @@
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
<<<LUA
- local cmd = redis.call
- if cmd('exists', KEYS[1]) == 1 then
- return cmd('incr', KEYS[1])
- end
+local cmd, insert = redis.call, table.insert
+local increment, results = ARGV[1], { }
+
+for idx, key in ipairs(KEYS) do
+ if cmd('exists', key) == 1 then
+ insert(results, idx, cmd('incrby', key, increment))
+ else
+ insert(results, idx, false)
+ end
+end
+
+return results
LUA;
}
}
$client = new Predis\Client($single_server, '2.6');
-$client->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,
+)
+*/
View
9 lib/Predis/Commands/ScriptedCommand.php
@@ -60,8 +60,13 @@ public function getKeys()
*/
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);
}
}
View
60 tests/Predis/Commands/ScriptedCommandTest.php
@@ -42,6 +42,25 @@ public function testGetArguments()
/**
* @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
+ */
public function testGetKeys()
{
$arguments = array('key1', 'key2', 'value1', 'value2');
@@ -61,6 +80,25 @@ public function testGetKeys()
/**
* @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
+ */
public function testPrefixKeys()
{
$arguments = array('foo', 'hoge', 'bar', 'piyo');
@@ -83,6 +121,28 @@ public function testPrefixKeys()
/**
* @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
+ */
public function testGetScriptHash()
{
$arguments = array('key1', 'key2', 'value1', 'value2');

0 comments on commit 5af2b62

Please sign in to comment.
Something went wrong with that request. Please try again.