Эх сурвалжийг харах

New command: SCAN (Redis 2.8).

See http://redis.io/commands/scan for reference.
Daniele Alessandri 11 жил өмнө
parent
commit
4eb4960b63

+ 76 - 0
lib/Predis/Command/KeyScan.php

@@ -0,0 +1,76 @@
+<?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/scan
+ * @author Daniele Alessandri <suppakilla@gmail.com>
+ */
+class KeyScan extends AbstractCommand
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getId()
+    {
+        return 'SCAN';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function filterArguments(Array $arguments)
+    {
+        if (count($arguments) === 2 && is_array($arguments[1])) {
+            $options = $this->prepareOptions(array_pop($arguments));
+            $arguments = array_merge($arguments, $options);
+        }
+
+        return $arguments;
+    }
+
+    /**
+     * Returns a list of options and modifiers compatible with Redis.
+     *
+     * @param array $options List of options.
+     * @return array
+     */
+    protected function prepareOptions($options)
+    {
+        $options = array_change_key_case($options, CASE_UPPER);
+        $normalized = array();
+
+        if (!empty($options['MATCH'])) {
+            $normalized[] = 'MATCH';
+            $normalized[] = $options['MATCH'];
+        }
+
+        if (!empty($options['COUNT'])) {
+            $normalized[] = 'COUNT';
+            $normalized[] = $options['COUNT'];
+        }
+
+        return $normalized;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function parseResponse($data)
+    {
+        if (is_array($data)) {
+            $data[0] = (int) $data[0];
+        }
+
+        return $data;
+    }
+}

+ 3 - 0
lib/Predis/Profile/ServerVersion28.php

@@ -236,6 +236,9 @@ class ServerVersion28 extends ServerProfile
 
 
             /* ---------------- Redis 2.8 ---------------- */
+
+            /* commands operating on the key space */
+            'scan'                      => 'Predis\Command\KeyScan',
         );
     }
 }

+ 1 - 0
lib/Predis/Replication/ReplicationStrategy.php

@@ -170,6 +170,7 @@ class ReplicationStrategy
             'EXISTS'            => true,
             'TYPE'              => true,
             'KEYS'              => true,
+            'SCAN'              => true,
             'RANDOMKEY'         => true,
             'TTL'               => true,
             'GET'               => true,

+ 138 - 0
tests/Predis/Command/KeyScanTest.php

@@ -0,0 +1,138 @@
+<?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;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+/**
+ * @group commands
+ * @group realm-key
+ */
+class KeyScanTest extends CommandTestCase
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function getExpectedCommand()
+    {
+        return 'Predis\Command\KeyScan';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function getExpectedId()
+    {
+        return 'SCAN';
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testFilterArguments()
+    {
+        $arguments = array(0, 'MATCH', 'key:*', 'COUNT', 5);
+        $expected = array(0, 'MATCH', 'key:*', 'COUNT', 5);
+
+        $command = $this->getCommand();
+        $command->setArguments($arguments);
+
+        $this->assertSame($expected, $command->getArguments());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testFilterArgumentsBasicUsage()
+    {
+        $arguments = array(0);
+        $expected = array(0);
+
+        $command = $this->getCommand();
+        $command->setArguments($arguments);
+
+        $this->assertSame($expected, $command->getArguments());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testFilterArgumentsWithOptionsArray()
+    {
+        $arguments = array(0, array('match' => 'key:*', 'count' => 5));
+        $expected = array(0, 'MATCH', 'key:*', 'COUNT', 5);
+
+        $command = $this->getCommand();
+        $command->setArguments($arguments);
+
+        $this->assertSame($expected, $command->getArguments());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testParseResponse()
+    {
+        $raw = array('3', array('key:1', 'key:2', 'key:3'));
+        $expected = array(3, array('key:1', 'key:2', 'key:3'));
+
+        $command = $this->getCommand();
+
+        $this->assertSame($expected, $command->parseResponse($raw));
+    }
+
+    /**
+     * @group connected
+     */
+    public function testScanWithoutMatch()
+    {
+        $kvs = array('key:one' => 'one', 'key:two' => 'two', 'key:three' => 'three', 'key:four' => 'four');
+
+        $redis = $this->getClient();
+        $redis->mset($kvs);
+
+        $response = $redis->scan(0);
+
+        $this->assertSameValues(array_keys($kvs), $response[1]);
+    }
+
+    /**
+     * @group connected
+     */
+    public function testScanWithMatchingKeys()
+    {
+        $kvs = array('key:one' => 'one', 'key:two' => 'two', 'key:three' => 'three', 'key:four' => 'four');
+
+        $redis = $this->getClient();
+        $redis->mset($kvs);
+
+        $response = $redis->scan(0, 'MATCH', 'key:t*');
+
+        $this->assertSameValues(array('key:two', 'key:three'), $response[1]);
+    }
+
+    /**
+     * @group connected
+     */
+    public function testScanWithNoMatchingKeys()
+    {
+        $kvs = array('key:one' => 'one', 'key:two' => 'two', 'key:three' => 'three', 'key:four' => 'four');
+
+        $redis = $this->getClient();
+        $redis->mset($kvs);
+
+        $response = $redis->scan(0, 'MATCH', 'nokey:*');
+
+        $this->assertSame(0, $response[0]);
+        $this->assertEmpty($response[1]);
+    }
+}

+ 1 - 0
tests/Predis/Profile/ServerVersion28Test.php

@@ -173,6 +173,7 @@ class ServerVersion28Test extends ServerVersionTestCase
             132 => 'evalsha',
             133 => 'script',
             134 => 'time',
+            135 => 'scan',
         );
     }
 }

+ 1 - 0
tests/Predis/Profile/ServerVersionNextTest.php

@@ -173,6 +173,7 @@ class ServerVersionNextTest extends ServerVersionTestCase
             132 => 'evalsha',
             133 => 'script',
             134 => 'time',
+            135 => 'scan',
         );
     }
 }

+ 1 - 0
tests/Predis/Replication/ReplicationStrategyTest.php

@@ -276,6 +276,7 @@ class ReplicationStrategyTest extends StandardTestCase
             'PTTL'                  => 'write',
             'SORT'                  => 'variable',
             'KEYS'                  => 'read',
+            'SCAN'                  => 'read',
             'RANDOMKEY'             => 'read',
 
             /* commands operating on string values */