Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpredis/phpredis.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavlo Yatsukhnenko <yatsukhnenko@gmail.com>2016-11-28 19:00:01 +0300
committerPavlo Yatsukhnenko <yatsukhnenko@gmail.com>2016-11-28 19:00:01 +0300
commit71c9f7c84c65c10dbe0ded9740f7dcce00da650c (patch)
treeb78cdd74bb0a4f45702fa7b9ffde4f8e764a2a98 /redis_commands.c
parent48c8f2a30a254b28194047c3720950fe53289210 (diff)
Issue #760
Diffstat (limited to 'redis_commands.c')
-rw-r--r--redis_commands.c75
1 files changed, 60 insertions, 15 deletions
diff --git a/redis_commands.c b/redis_commands.c
index c2c438c3..717b69e6 100644
--- a/redis_commands.c
+++ b/redis_commands.c
@@ -2577,25 +2577,57 @@ int redis_zadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char **cmd, int *cmd_len, short *slot, void **ctx)
{
zval *z_args;
- char *key, *val;
+ char *key, *val, *exp_type = NULL;
int key_len, key_free, val_len, val_free;
- int argc = ZEND_NUM_ARGS(), i;
+ int num = ZEND_NUM_ARGS(), i = 1, argc;
+ zend_bool ch = 0, incr = 0;
smart_string cmdstr = {0};
- z_args = emalloc(argc * sizeof(zval));
- if (zend_get_parameters_array(ht, argc, z_args) == FAILURE) {
+ if (num < 3) return FAILURE;
+ z_args = ecalloc(num, sizeof(zval));
+ if (zend_get_parameters_array(ht, num, z_args) == FAILURE) {
efree(z_args);
return FAILURE;
}
- // Need key, score, value, [score, value...] */
- if(argc>0) convert_to_string(&z_args[0]);
- if(argc<3 || Z_TYPE(z_args[0])!=IS_STRING || (argc-1)%2 != 0) {
- efree(z_args);
- return FAILURE;
+ // Need key, [NX|XX] [CH] [INCR] score, value, [score, value...] */
+ if (num % 2 == 0) {
+ if (Z_TYPE(z_args[1]) != IS_ARRAY) {
+ efree(z_args);
+ return FAILURE;
+ }
+ zval *z_opt;
+ ZEND_HASH_FOREACH_VAL(Z_ARRVAL(z_args[1]), z_opt) {
+ if (Z_TYPE_P(z_opt) == IS_STRING) {
+ if (Z_STRLEN_P(z_opt) == 2) {
+ if (IS_NX_XX_ARG(Z_STRVAL_P(z_opt))) {
+ exp_type = Z_STRVAL_P(z_opt);
+ } else if (strncasecmp(Z_STRVAL_P(z_opt), "ch", 2) == 0) {
+ ch = 1;
+ }
+ } else if (Z_STRLEN_P(z_opt) == 4 &&
+ strncasecmp(Z_STRVAL_P(z_opt), "incr", 4) == 0
+ ) {
+ if (num > 4) {
+ // Only one score-element pair can be specified in this mode.
+ efree(z_args);
+ return FAILURE;
+ }
+ incr = 1;
+ }
+
+ }
+ } ZEND_HASH_FOREACH_END();
+ argc = num - 1;
+ if (exp_type) argc++;
+ argc += ch + incr;
+ i++;
+ } else {
+ argc = num;
}
// Prefix our key
+ convert_to_string(&z_args[0]);
key = Z_STRVAL(z_args[0]);
key_len = Z_STRLEN(z_args[0]);
key_free = redis_key_prefix(redis_sock, &key, &key_len);
@@ -2608,19 +2640,32 @@ int redis_zadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
CMD_SET_SLOT(slot,key,key_len);
if(key_free) efree(key);
+ if (exp_type) redis_cmd_append_sstr(&cmdstr, exp_type, 2);
+ if (ch) redis_cmd_append_sstr(&cmdstr, "CH", 2);
+ if (incr) redis_cmd_append_sstr(&cmdstr, "INCR", 4);
+
// Now the rest of our arguments
- for(i=1;i<argc;i+=2) {
- // Convert score to a double, serialize value if requested
- convert_to_double(&z_args[i]);
+ while (i < num) {
+ // Append score and member
+ if (Z_TYPE(z_args[i]) == IS_STRING && (
+ /* The score values should be the string representation of a double
+ * precision floating point number. +inf and -inf values are valid
+ * values as well. */
+ strncasecmp(Z_STRVAL(z_args[i]), "-inf", 4) == 0 ||
+ strncasecmp(Z_STRVAL(z_args[i]), "+inf", 4) == 0
+ )) {
+ redis_cmd_append_sstr(&cmdstr, Z_STRVAL(z_args[i]), Z_STRLEN(z_args[i]));
+ } else {
+ redis_cmd_append_sstr_dbl(&cmdstr, zval_get_double(&z_args[i]));
+ }
+ // serialize value if requested
val_free = redis_serialize(redis_sock, &z_args[i+1], &val, &val_len
TSRMLS_CC);
-
- // Append score and member
- redis_cmd_append_sstr_dbl(&cmdstr, Z_DVAL(z_args[i]));
redis_cmd_append_sstr(&cmdstr, val, val_len);
// Free value if we serialized
if(val_free) efree(val);
+ i += 2;
}
// Push output values