瀏覽代碼

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.
Daniele Alessandri 13 年之前
父節點
當前提交
ca7bd8149f
共有 3 個文件被更改,包括 95 次插入13 次删除
  1. 28 11
      examples/ServerSideScripting.php
  2. 7 2
      lib/Predis/Command/ScriptedCommand.php
  3. 60 0
      tests/Predis/Command/ScriptedCommandTest.php

+ 28 - 11
examples/ServerSideScripting.php

@@ -20,30 +20,47 @@ require 'SharedConfigurations.php';
 
 use Predis\Command\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 = new Predis\Client($single_server);
 
-$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,
+)
+*/

+ 7 - 2
lib/Predis/Command/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);
     }
 }

+ 60 - 0
tests/Predis/Command/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\Command\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\Command\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\Command\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
      */