Permalink
Browse files

Implemented INCRBYFLOAT and HINCRBYFLOAT

  • Loading branch information...
1 parent 3160a64 commit d59b53b6b5779113ef8bf4d6f951bddd75e7f99d @michael-grunder michael-grunder committed May 4, 2012
Showing with 130 additions and 10 deletions.
  1. +2 −0 library.c
  2. +2 −0 php_redis.h
  3. +87 −2 redis.c
  4. +39 −8 tests/TestRedis.php
View
@@ -566,6 +566,8 @@ PHPAPI void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
}
}
+
+
PHPAPI int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, int flag) {
/*
View
@@ -44,6 +44,7 @@ PHP_METHOD(Redis, exists);
PHP_METHOD(Redis, delete);
PHP_METHOD(Redis, incr);
PHP_METHOD(Redis, incrBy);
+PHP_METHOD(Redis, incrByFloat);
PHP_METHOD(Redis, decr);
PHP_METHOD(Redis, decrBy);
PHP_METHOD(Redis, type);
@@ -141,6 +142,7 @@ PHP_METHOD(Redis, hVals);
PHP_METHOD(Redis, hGetAll);
PHP_METHOD(Redis, hExists);
PHP_METHOD(Redis, hIncrBy);
+PHP_METHOD(Redis, hIncrByFloat);
PHP_METHOD(Redis, hMset);
PHP_METHOD(Redis, hMget);
View
@@ -91,6 +91,7 @@ static zend_function_entry redis_functions[] = {
PHP_ME(Redis, delete, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, incr, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, incrBy, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Redis, incrByFloat, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, decr, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, decrBy, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, type, NULL, ZEND_ACC_PUBLIC)
@@ -189,6 +190,7 @@ static zend_function_entry redis_functions[] = {
PHP_ME(Redis, hGetAll, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hExists, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hIncrBy, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Redis, hIncrByFloat, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hMset, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hMget, NULL, ZEND_ACC_PUBLIC)
@@ -1048,6 +1050,38 @@ PHP_METHOD(Redis, incrBy){
}
/* }}} */
+/* {{{ proto float Redis::incrByFloat(string key, float value)
+ */
+PHP_METHOD(Redis, incrByFloat) {
+ zval *object;
+ RedisSock *redis_sock;
+ char *key = NULL, *cmd;
+ int key_len, cmd_len, key_free;
+ double val;
+
+ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osd",
+ &object, redis_ce, &key, &key_len, &val) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) {
+ RETURN_FALSE;
+ }
+
+ // Prefix our key, free it if we have
+ key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC);
+ if(key_free) efree(key);
+
+ // Format our INCRBYFLOAT command
+ cmd_len = redis_cmd_format_static(&cmd, "INCRBYFLOAT", "sf", key, key_len, val);
+
+ REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
+ IF_ATOMIC() {
+ redis_bulk_double_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL);
+ }
+ REDIS_PROCESS_RESPONSE(redis_bulk_double_response);
+}
+
/* {{{ proto boolean Redis::decr(string key [,int value])
*/
PHP_METHOD(Redis, decr)
@@ -4506,6 +4540,59 @@ PHPAPI void array_zip_values_and_scores(RedisSock *redis_sock, zval *z_tab, int
efree(z_ret);
}
+PHP_METHOD(Redis, hIncrByFloat)
+{
+ zval *object;
+ RedisSock *redis_sock;
+ char *key = NULL, *cmd, *member;
+ int key_len, member_len, cmd_len, val_len, key_free;
+ double val;
+ int i, dcount;
+
+ // Validate we have the right number of arguments
+ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ossd",
+ &object, redis_ce,
+ &key, &key_len, &member, &member_len, &val) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ // Grab our socket
+ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) {
+ RETURN_FALSE;
+ }
+
+ // Start at the begining unless the first character is '-'
+ /*i = val_len && val[0] == '-' ? 1 : 0;
+
+ // Initially we have no '.' characters
+ dcount = 0;
+
+ // Iterate our string
+ for(; i<val_len; ++i) {
+ // Increment our decimal count and skip this iteration if we're on one
+ if(val[i] == '.') {
+ ++dcount;
+ continue;
+ }
+
+ // We're invalid if this character isn't numeric, or if we have too many decimals
+ if((val[i] < '0' || val[i] > '9') || dcount > 1) {
+ RETURN_FALSE;
+ }
+ }
+ */
+
+ key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC);
+ cmd_len = redis_cmd_format_static(&cmd, "HINCRBYFLOAT", "ssf", key, key_len, member, member_len, val);
+ if(key_free) efree(key);
+
+ REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
+ IF_ATOMIC() {
+ redis_bulk_double_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL);
+ }
+ REDIS_PROCESS_RESPONSE(redis_bulk_double_response);
+}
+
PHP_METHOD(Redis, hIncrBy)
{
zval *object;
@@ -4535,8 +4622,6 @@ PHP_METHOD(Redis, hIncrBy)
}
}
-
-
/* HINCRBY key member amount */
key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC);
cmd_len = redis_cmd_format_static(&cmd, "HINCRBY", "sss", key, key_len, member, member_len, val, val_len);
View
@@ -354,7 +354,7 @@ public function testIncr()
$this->redis->incr('key');
$this->assertEquals(2, (int)$this->redis->get('key'));
- $this->redis->incr('key', 3);
+ $this->redis->incr('key', 3);
$this->assertEquals(5, (int)$this->redis->get('key'));
$this->redis->incrBy('key', 3);
@@ -376,6 +376,28 @@ public function testIncr()
$this->redis->incr('key');
$this->assertTrue("abc" === $this->redis->get('key'));
+ // incrbyfloat
+
+ $this->redis->delete('key');
+
+ $this->redis->set('key', 0);
+
+ $this->redis->incrbyfloat('key', 1.5);
+ $this->assertEquals('1.5', $this->redis->get('key'));
+
+ $this->redis->incrbyfloat('key', 2.25);
+ $this->assertEquals('3.75', $this->redis->get('key'));
+
+ $this->redis->incrbyfloat('key', -2.25);
+ $this->assertEquals('1.5', $this->redis->get('key'));
+
+ $this->redis->set('key', 'abc');
+
+ $this->redis->incrbyfloat('key', 1.5);
+ $this->assertTrue("abc" === $this->redis->get('key'));
+
+ $this->redis->incrbyfloat('key', -1.5);
+ $this->assertTrue("abc" === $this->redis->get('key'));
}
public function testDecr()
@@ -627,16 +649,16 @@ public function testblockingPop() {
// TODO: fix this broken test.
// $this->redis->delete('list');
// $params = array(
-// 0 => array("pipe", "r"),
+// 0 => array("pipe", "r"),
// 1 => array("pipe", "w"),
// 2 => array("file", "/dev/null", "w")
// );
// if(function_exists('proc_open')) {
// $env = array('PHPREDIS_key' =>'list', 'PHPREDIS_value' => 'value');
// $process = proc_open('php', $params, $pipes, '/tmp', $env);
-//
+//
// if (is_resource($process)) {
-// fwrite($pipes[0], '<?php
+// fwrite($pipes[0], '<?php
// sleep(2);
// $r = new Redis;
// $r->connect("'.self::HOST.'", '.self::PORT.');
@@ -645,11 +667,11 @@ public function testblockingPop() {
// }
// $r->lPush($_ENV["PHPREDIS_key"], $_ENV["PHPREDIS_value"]);
// ?' . '>');
-//
+//
// fclose($pipes[0]);
// fclose($pipes[1]);
// $re = proc_close($process);
-//
+//
// $this->assertTrue($this->redis->blPop(array('list'), 5) === array("list", "value"));
// }
// }
@@ -684,8 +706,8 @@ public function testlSize()
}
//lInsert, lPopx, rPopx
- public function testlPopx() {
- //test lPushx/rPushx
+ public function testlPopx() {
+ //test lPushx/rPushx
$this->redis->delete('keyNotExists');
$this->assertTrue($this->redis->lPushx('keyNotExists', 'value') === 0);
$this->assertTrue($this->redis->rPushx('keyNotExists', 'value') === 0);
@@ -1909,6 +1931,15 @@ public function testHashes() {
$this->redis->hSet('h', 'y', 'not-a-number');
$this->assertTrue(FALSE === $this->redis->hIncrBy('h', 'y', 1));
+ // hIncrByFloat
+ $this->redis->delete('h');
+ $this->assertTrue('1.5' === $this->redis->hIncrByFloat('h','x', 1.5));
+ $this->assertTrue('3.0' === $this->redis->hincrByFloat('h','x', 1.5));
+ $this->assertTrue('1.5' === $this->redis->hincrByFloat('h','x', -1.5));
+
+ $this->redis->hset('h','y','not-a-number');
+ $this->assertTrue(FALSE === $this->redis->hIncrByFloat('h', 'y', 1.5));
+
// hmset
$this->redis->delete('h');
$this->assertTrue(TRUE === $this->redis->hMset('h', array('x' => 123, 'y' => 456, 'z' => 'abc')));

0 comments on commit d59b53b

Please sign in to comment.