diff options
author | Nicolas Favre-Felix <n.favrefelix@gmail.com> | 2011-11-27 23:52:03 +0400 |
---|---|---|
committer | Nicolas Favre-Felix <n.favrefelix@gmail.com> | 2011-11-27 23:52:03 +0400 |
commit | 1ce8bcc5340bcf928ccca72a043ec0c44a4e19ac (patch) | |
tree | 6803fcb893ddb150b5d42e086270b995b12d7cf3 | |
parent | 9692ad980d6abc80e00a1fb960737e824581507b (diff) |
Added missing DISCARD in RedisArray mode.
Also added a unit test covering this feature.
This commit fixes GitHub issue #87.
-rw-r--r-- | redis_array.c | 22 | ||||
-rw-r--r-- | redis_array.h | 1 | ||||
-rw-r--r-- | redis_array_impl.c | 12 | ||||
-rw-r--r-- | redis_array_impl.h | 1 | ||||
-rw-r--r-- | tests/array-tests.php | 32 |
5 files changed, 68 insertions, 0 deletions
diff --git a/redis_array.c b/redis_array.c index 1d8fd415..cf67cfe2 100644 --- a/redis_array.c +++ b/redis_array.c @@ -60,6 +60,7 @@ zend_function_entry redis_array_functions[] = { /* Multi/Exec */ PHP_ME(RedisArray, multi, NULL, ZEND_ACC_PUBLIC) PHP_ME(RedisArray, exec, NULL, ZEND_ACC_PUBLIC) + PHP_ME(RedisArray, discard, NULL, ZEND_ACC_PUBLIC) /* Aliases */ PHP_MALIAS(RedisArray, delete, del, NULL, ZEND_ACC_PUBLIC) @@ -1027,3 +1028,24 @@ PHP_METHOD(RedisArray, exec) /* remove multi object */ ra->z_multi_exec = NULL; } + +PHP_METHOD(RedisArray, discard) +{ + zval *object; + RedisArray *ra; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, redis_array_ce) == FAILURE) { + RETURN_FALSE; + } + + if (redis_array_get(object, &ra TSRMLS_CC) < 0 || !ra->z_multi_exec) { + RETURN_FALSE; + } + + /* switch redis instance out of multi/exec mode. */ + ra_index_discard(ra->z_multi_exec, return_value TSRMLS_CC); + + /* remove multi object */ + ra->z_multi_exec = NULL; +} diff --git a/redis_array.h b/redis_array.h index 51d950f2..dfedbca5 100644 --- a/redis_array.h +++ b/redis_array.h @@ -23,6 +23,7 @@ PHP_METHOD(RedisArray, setOption); PHP_METHOD(RedisArray, multi); PHP_METHOD(RedisArray, exec); +PHP_METHOD(RedisArray, discard); typedef struct RedisArray_ { diff --git a/redis_array_impl.c b/redis_array_impl.c index a0496b0e..c7f475d3 100644 --- a/redis_array_impl.c +++ b/redis_array_impl.c @@ -516,6 +516,18 @@ ra_index_exec(zval *z_redis, zval *return_value, int keep_all TSRMLS_DC) { //php_var_dump(&zptr, 0 TSRMLS_CC); } +void +ra_index_discard(zval *z_redis, zval *return_value TSRMLS_DC) { + + zval z_fun_discard, z_ret; + + /* run DISCARD */ + ZVAL_STRING(&z_fun_discard, "DISCARD", 0); + call_user_function(&redis_ce->function_table, &z_redis, &z_fun_discard, &z_ret, 0, NULL TSRMLS_CC); + + zval_dtor(&z_ret); +} + zend_bool ra_is_write_cmd(RedisArray *ra, const char *cmd, int cmd_len) { diff --git a/redis_array_impl.h b/redis_array_impl.h index e56c6742..c42a97a7 100644 --- a/redis_array_impl.h +++ b/redis_array_impl.h @@ -20,6 +20,7 @@ void ra_index_key(const char *key, int key_len, zval *z_redis TSRMLS_DC); void ra_index_keys(zval *z_pairs, zval *z_redis TSRMLS_DC); void ra_index_del(zval *z_keys, zval *z_redis TSRMLS_DC); void ra_index_exec(zval *z_redis, zval *return_value, int keep_all TSRMLS_DC); +void ra_index_discard(zval *z_redis, zval *return_value TSRMLS_DC); zend_bool ra_is_write_cmd(RedisArray *ra, const char *cmd, int cmd_len); void ra_rehash(RedisArray *ra, zval *z_cb TSRMLS_DC); diff --git a/tests/array-tests.php b/tests/array-tests.php index aa916478..7bf40038 100644 --- a/tests/array-tests.php +++ b/tests/array-tests.php @@ -426,6 +426,38 @@ class Redis_Multi_Exec_Test extends TestSuite { $this->assertTrue($this->ra->exists('1_{employee:joe}_salary') === FALSE); } + public function testDiscard() { + /* phpredis issue #87 */ + $key = 'test_err'; + + $this->assertTrue($this->ra->set($key, 'test')); + $this->assertTrue('test' === $this->ra->get($key)); + + $this->ra->watch($key); + + // After watch, same + $this->assertTrue('test' === $this->ra->get($key)); + + // change in a multi/exec block. + $ret = $this->ra->multi($this->ra->_target($key))->set($key, 'test1')->exec(); + $this->assertTrue($ret === array(true)); + + // Get after exec, 'test1': + $this->assertTrue($this->ra->get($key) === 'test1'); + + $this->ra->watch($key); + + // After second watch, still test1. + $this->assertTrue($this->ra->get($key) === 'test1'); + + $ret = $this->ra->multi($this->ra->_target($key))->set($key, 'test2')->discard(); + // Ret after discard: NULL"; + $this->assertTrue($ret === NULL); + + // Get after discard, unchanged: + $this->assertTrue($this->ra->get($key) === 'test1'); + } + } |