diff --git a/lib/Predis.php b/lib/Predis.php index cca9ff65..6c4d5c58 100644 --- a/lib/Predis.php +++ b/lib/Predis.php @@ -773,6 +773,7 @@ class MultiExecBlock { $this->checkCapabilities($redisClient); $this->_initialized = false; $this->_discarded = false; + $this->_checkAndSet = false; $this->_insideBlock = false; $this->_redisClient = $redisClient; $this->_options = $options ?: array(); @@ -804,10 +805,14 @@ class MultiExecBlock { private function initialize() { if ($this->_initialized === false) { - if (isset($this->_options['watch'])) { - $this->watch($this->_options['watch']); + $options = &$this->_options; + $this->_checkAndSet = isset($options['cas']) && $options['cas']; + if (isset($options['watch'])) { + $this->watch($options['watch']); + } + if (!$this->_checkAndSet) { + $this->_redisClient->multi(); } - $this->_redisClient->multi(); $this->_initialized = true; $this->_discarded = false; } @@ -819,8 +824,14 @@ class MultiExecBlock { public function __call($method, $arguments) { $this->initialize(); - $command = $this->_redisClient->createCommand($method, $arguments); - $response = $this->_redisClient->executeCommand($command); + $client = $this->_redisClient; + + if ($this->_checkAndSet) { + return call_user_func_array(array($client, $method), $arguments); + } + + $command = $client->createCommand($method, $arguments); + $response = $client->executeCommand($command); if (isset($response->queued)) { $this->_commands[] = $command; return $this; @@ -850,6 +861,11 @@ class MultiExecBlock { } public function multi() { + if ($this->_initialized && $this->_checkAndSet) { + $this->_checkAndSet = false; + $this->_redisClient->multi(); + return $this; + } $this->initialize(); } diff --git a/test/PredisClientFeatures.php b/test/PredisClientFeatures.php index e44d38a2..384b5196 100644 --- a/test/PredisClientFeatures.php +++ b/test/PredisClientFeatures.php @@ -649,5 +649,32 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase { $this->assertEquals('client2', $client1->get('sentinel')); } + + function testMultiExecBlock_CheckAndSet() { + $client = RC::getConnection(); + $client->flushdb(); + $client->set('foo', 'bar'); + + $options = array('watch' => 'foo', 'cas' => true); + $replies = $client->multiExec($options, function($tx) { + $tx->watch('foobar'); + $foo = $tx->get('foo'); + $tx->multi(); + $tx->set('foobar', $foo); + $tx->mget('foo', 'foobar'); + }); + $this->assertType('array', $replies); + $this->assertEquals(array(true, array('bar', 'bar')), $replies); + + $tx = $client->multiExec($options); + $tx->watch('foobar'); + $foo = $tx->get('foo'); + $replies = $tx->multi() + ->set('foobar', $foo) + ->mget('foo', 'foobar') + ->execute(); + $this->assertType('array', $replies); + $this->assertEquals(array(true, array('bar', 'bar')), $replies); + } } ?>