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:
-rw-r--r--README.markdown25
-rw-r--r--common.h9
-rw-r--r--library.c1
-rw-r--r--php_redis.h1
-rw-r--r--redis.c192
-rw-r--r--tests/TestRedis.php69
-rw-r--r--tests/test.php15
7 files changed, 224 insertions, 88 deletions
diff --git a/README.markdown b/README.markdown
index fbf7d742..cb32804b 100644
--- a/README.markdown
+++ b/README.markdown
@@ -2488,6 +2488,7 @@ while(($arr_mems = $redis->sscan('set', $it, "*pattern*"))!==FALSE) {
* [zInter](#zinter) - Intersect multiple sorted sets and store the resulting sorted set in a new key
* [zRange](#zrange) - Return a range of members in a sorted set, by index
* [zRangeByScore, zRevRangeByScore](#zrangebyscore-zrevrangebyscore) - Return a range of members in a sorted set, by score
+* [zRangeByLex](#zrangebylex) - Return a lexigraphical range from members that share the same score
* [zRank, zRevRank](#zrank-zrevrank) - Determine the index of a member in a sorted set
* [zRem, zDelete](#zrem-zdelete) - Remove one or more members from a sorted set
* [zRemRangeByRank, zDeleteRangeByRank](#zremrangebyrank-zdeleterangebyrank) - Remove all members in a sorted set within the given indexes
@@ -2671,6 +2672,30 @@ $redis->zRangeByScore('key', 0, 3, array('limit' => array(1, 1)); /* array('val2
$redis->zRangeByScore('key', 0, 3, array('withscores' => TRUE, 'limit' => array(1, 1)); /* array('val2' => 2) */
~~~
+### zRangeByLex
+-----
+_**Description**_: Returns a lexigraphical range of members in a sorted set, assuming the members have the same score. The min and max values are required to start with '(' (exclusive), '[' (inclusive), or be exactly the values '-' (negative inf) or '+' (positive inf). The command must be called with either three *or* five arguments or will return FALSE.
+
+##### *Parameters*
+*key*: The ZSET you wish to run against
+*min*: The minimum alphanumeric value you wish to get
+*max*: The maximum alphanumeric value you wish to get
+*offset*: Optional argument if you wish to start somewhere other than the first element.
+*limit*: Optional argument if you wish to limit the number of elements returned.
+
+##### *Return value*
+*Array* containing the values in the specified range.
+
+##### *Example*
+~~~
+foreach(Array('a','b','c','d','e','f','g') as $c)
+ $redis->zAdd('key',0,$c);
+
+$redis->zRangeByLex('key','-','[c') /* Array('a','b','c'); */
+$redis->zRangeByLex('key','-','(c') /* Array('a','b') */
+$redis->zRangeByLex('key','-','[c',1,2) /* Array('b','c') */
+~~~
+
### zRank, zRevRank
-----
_**Description**_: Returns the rank of a given member in the specified sorted set, starting at 0 for the item with the smallest score. zRevRank starts at 0 for the item with the *largest* score.
diff --git a/common.h b/common.h
index a0623fbd..a46d006a 100644
--- a/common.h
+++ b/common.h
@@ -30,7 +30,8 @@
/* reply types */
typedef enum _REDIS_REPLY_TYPE {
- TYPE_LINE = '+',
+ TYPE_EOF = EOF,
+ TYPE_LINE = '+',
TYPE_INT = ':',
TYPE_ERR = '-',
TYPE_BULK = '$',
@@ -178,6 +179,12 @@ else if(redis_sock->mode == MULTI) { \
#define IS_EX_PX_ARG(a) (IS_EX_ARG(a) || IS_PX_ARG(a))
#define IS_NX_XX_ARG(a) (IS_NX_ARG(a) || IS_XX_ARG(a))
+/* Given a string and length, validate a zRangeByLex argument. The semantics
+ * here are that the argument must start with '(' or '[' or be just the char
+ * '+' or '-' */
+#define IS_LEX_ARG(s,l) \
+ (l>0 && (*s=='(' || *s=='[' || (l==1 && (*s=='+' || *s=='-'))))
+
typedef enum {ATOMIC, MULTI, PIPELINE} redis_mode;
typedef struct fold_item {
diff --git a/library.c b/library.c
index 40d43fa2..3c67a2d0 100644
--- a/library.c
+++ b/library.c
@@ -1911,6 +1911,7 @@ redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, zval **z_ret
add_next_index_zval(*z_ret, z_subelem);
redis_read_multibulk_recursive(redis_sock, reply_info, &z_subelem TSRMLS_CC);
break;
+ default: break; /* We know it's not < 0 from previous check */
}
/* Decrement our element counter */
diff --git a/php_redis.h b/php_redis.h
index 437d0df8..23e26310 100644
--- a/php_redis.h
+++ b/php_redis.h
@@ -111,6 +111,7 @@ PHP_METHOD(Redis, zDelete);
PHP_METHOD(Redis, zRange);
PHP_METHOD(Redis, zReverseRange);
PHP_METHOD(Redis, zRangeByScore);
+PHP_METHOD(Redis, zRangeByLex);
PHP_METHOD(Redis, zRevRangeByScore);
PHP_METHOD(Redis, zCount);
PHP_METHOD(Redis, zDeleteRangeByScore);
diff --git a/redis.c b/redis.c
index 1d0cd640..02c0eb21 100644
--- a/redis.c
+++ b/redis.c
@@ -192,6 +192,7 @@ static zend_function_entry redis_functions[] = {
PHP_ME(Redis, zReverseRange, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zRangeByScore, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zRevRangeByScore, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Redis, zRangeByLex, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zCount, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zDeleteRangeByScore, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zDeleteRangeByRank, NULL, ZEND_ACC_PUBLIC)
@@ -316,8 +317,8 @@ static zend_function_entry redis_functions[] = {
PHP_MALIAS(Redis, srem, sRemove, NULL, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, sismember, sContains, NULL, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, zrevrange, zReverseRange, NULL, ZEND_ACC_PUBLIC)
-
- PHP_MALIAS(Redis, sendEcho, echo, NULL, ZEND_ACC_PUBLIC)
+
+ PHP_MALIAS(Redis, sendEcho, echo, NULL, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, evaluate, eval, NULL, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, evaluateSha, evalsha, NULL, ZEND_ACC_PUBLIC)
@@ -476,7 +477,7 @@ PHP_MINIT_FUNCTION(redis)
zend_class_entry redis_exception_class_entry;
REGISTER_INI_ENTRIES();
-
+
/* Redis class */
INIT_CLASS_ENTRY(redis_class_entry, "Redis", redis_functions);
redis_ce = zend_register_internal_class(&redis_class_entry TSRMLS_CC);
@@ -652,7 +653,7 @@ PHP_REDIS_API int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
char *persistent_id = NULL;
int persistent_id_len = -1;
-
+
double timeout = 0.0;
RedisSock *redis_sock = NULL;
@@ -832,7 +833,7 @@ PHP_METHOD(Redis, bitcount)
/* }}} */
/* {{{ proto integer Redis::bitpos(string key, int bit, [int start], [int end]) */
-PHP_METHOD(Redis, bitpos)
+PHP_METHOD(Redis, bitpos)
{
zval *object;
RedisSock *redis_sock;
@@ -934,7 +935,7 @@ PHP_METHOD(Redis, set) {
/* Our optional argument can either be a long (to support legacy SETEX */
/* redirection), or an array with Redis >= 2.6.12 set options */
if(z_opts && Z_TYPE_P(z_opts) != IS_LONG && Z_TYPE_P(z_opts) != IS_ARRAY
- && Z_TYPE_P(z_opts) != IS_NULL)
+ && Z_TYPE_P(z_opts) != IS_NULL)
{
RETURN_FALSE;
}
@@ -1430,7 +1431,7 @@ PHP_METHOD(Redis, incrByFloat) {
/* Prefix key, format command, free old key if necissary */
key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC);
cmd_len = redis_cmd_format_static(&cmd, "INCRBYFLOAT", "sf", key, key_len, val);
- if(key_free) efree(key);
+ if(key_free) efree(key);
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
IF_ATOMIC() {
@@ -1992,11 +1993,11 @@ PHP_METHOD(Redis, lInsert)
int pivot_len, position_len, key_len, val_len, cmd_len;
int val_free, pivot_free, key_free;
zval *z_value, *z_pivot;
-
+
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osszz",
&object, redis_ce,
- &key, &key_len,
+ &key, &key_len,
&position, &position_len,
&z_pivot,
&z_value) == FAILURE) {
@@ -2006,7 +2007,7 @@ PHP_METHOD(Redis, lInsert)
if (redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) {
RETURN_FALSE;
}
-
+
if(strncasecmp(position, "after", 5) == 0 || strncasecmp(position, "before", 6) == 0) {
key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC);
@@ -2017,15 +2018,15 @@ PHP_METHOD(Redis, lInsert)
if(key_free) efree(key);
if(pivot_free) STR_FREE(pivot);
- REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
- IF_ATOMIC() {
- redis_long_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL);
- }
- REDIS_PROCESS_RESPONSE(redis_long_response);
+ REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
+ IF_ATOMIC() {
+ redis_long_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL);
+ }
+ REDIS_PROCESS_RESPONSE(redis_long_response);
} else {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error on position");
}
-
+
}
PHP_METHOD(Redis, lPushx)
@@ -2669,7 +2670,7 @@ PHP_REDIS_API int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char *
if(has_timeout && Z_TYPE_P(z_args[argc - 1]) != IS_LONG) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Syntax error on timeout");
}
-
+
for(i = 0, j = 0; i < argc; ++i) { /* store each key */
if(!all_keys && j != 0) { /* not just operating on keys */
@@ -2683,7 +2684,7 @@ PHP_REDIS_API int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char *
}
} else {
-
+
if(Z_TYPE_P(z_args[i]) != IS_STRING) {
convert_to_string(z_args[i]);
}
@@ -2707,7 +2708,7 @@ PHP_REDIS_API int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char *
cmd = emalloc(cmd_len+1);
sprintf(cmd, "*%d" _NL "$%d" _NL "%s" _NL, 1+real_argc, keyword_len, keyword);
-
+
pos = 1 +integer_length(real_argc + 1) + 2
+ 1 + integer_length(keyword_len) + 2
+ keyword_len + 2;
@@ -4314,6 +4315,65 @@ PHP_METHOD(Redis, zCount)
}
/* }}} */
+/* {{{ proto array Redis::zRangeByLex(string $key, string $min, string $max,
+ * [long $offset, long $count]) */
+PHP_METHOD(Redis, zRangeByLex) {
+ zval *object;
+ RedisSock *redis_sock;
+ char *cmd, *key, *min, *max;
+ long offset, count;
+ int argc, cmd_len, key_len;
+ int key_free, min_len, max_len;
+
+ /* We need either three or five arguments for this to be a valid call */
+ argc = ZEND_NUM_ARGS();
+ if (argc != 3 && argc != 5) {
+ RETURN_FALSE;
+ }
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
+ "Osss|ll", &object, redis_ce, &key, &key_len,
+ &min, &min_len, &max, &max_len, &offset,
+ &count) == FAILURE)
+ {
+ RETURN_FALSE;
+ }
+
+ /* We can do some simple validation for the user, as we know how min/max are
+ * required to start */
+ if (!IS_LEX_ARG(min,min_len) || !IS_LEX_ARG(max,max_len)) {
+ RETURN_FALSE;
+ }
+
+ if (redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) {
+ RETURN_FALSE;
+ }
+
+ key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC);
+
+ /* Construct our command depending on argc */
+ if (argc == 3) {
+ cmd_len = redis_cmd_format_static(&cmd, "ZRANGEBYLEX", "sss", key,
+ key_len, min, min_len, max, max_len);
+ } else {
+ cmd_len = redis_cmd_format_static(&cmd, "ZRANGEBYLEX", "ssssll", key,
+ key_len, min, min_len, max, max_len, "LIMIT", sizeof("LIMIT")-1,
+ offset, count);
+ }
+
+ if(key_free) efree(key);
+
+ /* Kick it off */
+ REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
+ IF_ATOMIC() {
+ if (redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
+ redis_sock, NULL, NULL) < 0) {
+ RETURN_FALSE;
+ }
+ }
+ REDIS_PROCESS_RESPONSE(redis_sock_read_multibulk_reply);
+}
+
/* {{{ proto long Redis::zCard(string key)
*/
PHP_METHOD(Redis, zCard)
@@ -4906,7 +4966,7 @@ PHP_REDIS_API void array_zip_values_and_scores(RedisSock *redis_sock, zval *z_ta
zval *z_ret;
HashTable *keytable;
-
+
MAKE_STD_ZVAL(z_ret);
array_init(z_ret);
keytable = Z_ARRVAL_P(z_tab);
@@ -5081,7 +5141,7 @@ PHP_METHOD(Redis, hMget) {
/* Make sure the data is a long or string, and if it's a string that */
/* it isn't empty. There is no reason to send empty length members. */
if((Z_TYPE_PP(data) == IS_STRING && Z_STRLEN_PP(data)>0) ||
- Z_TYPE_PP(data) == IS_LONG)
+ Z_TYPE_PP(data) == IS_LONG)
{
/* This is a key we can ask for, copy it and set it in our array */
MAKE_STD_ZVAL(z_keys[valid]);
@@ -5166,7 +5226,7 @@ PHP_METHOD(Redis, hMset)
unsigned long idx;
int type;
zval **z_value_p;
-
+
char *hval;
int hval_len, hval_free;
@@ -5361,7 +5421,7 @@ free_reply_callbacks(zval *z_this, RedisSock *redis_sock) {
fold_item *fi;
fold_item *head = redis_sock->head;
request_item *ri;
-
+
for(fi = head; fi; ) {
fold_item *fi_next = fi->next;
free(fi);
@@ -5508,9 +5568,9 @@ PHP_METHOD(Redis, pipeline)
RETURN_ZVAL(getThis(), 1, 0);
}
-/*
- publish channel message
- @return the number of subscribers
+/*
+ publish channel message
+ @return the number of subscribers
*/
PHP_METHOD(Redis, publish)
{
@@ -5556,10 +5616,10 @@ PHP_REDIS_API void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub
zend_fcall_info_cache z_callback_cache;
zval *z_ret, **z_args[4];
-
+
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oaf",
&object, redis_ce, &array, &z_callback, &z_callback_cache) == FAILURE) {
- RETURN_FALSE;
+ RETURN_FALSE;
}
if (redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) {
@@ -5611,9 +5671,9 @@ PHP_REDIS_API void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub
RETURN_FALSE;
}
efree(cmd);
-
+
/* read the status of the execution of the command `subscribe` */
-
+
z_tab = redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
if(z_tab == NULL) {
RETURN_FALSE;
@@ -5624,16 +5684,16 @@ PHP_REDIS_API void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub
if(strcmp(type_response, sub_cmd) != 0) {
efree(tmp);
zval_dtor(z_tab);
- efree(z_tab);
+ efree(z_tab);
RETURN_FALSE;
- }
+ }
} else {
zval_dtor(z_tab);
- efree(z_tab);
+ efree(z_tab);
RETURN_FALSE;
}
zval_dtor(z_tab);
- efree(z_tab);
+ efree(z_tab);
/* Set a pointer to our return value and to our arguments. */
z_callback.retval_ptr_ptr = &z_ret;
@@ -5641,12 +5701,12 @@ PHP_REDIS_API void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub
z_callback.no_separation = 0;
/* Multibulk Response, format : {message type, originating channel, message payload} */
- while(1) {
+ while(1) {
/* call the callback with this z_tab in argument */
int is_pmsg, tab_idx = 1;
zval **type, **channel, **pattern, **data;
z_tab = redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
-
+
if(z_tab == NULL || Z_TYPE_P(z_tab) != IS_ARRAY) {
/*ERROR */
break;
@@ -5732,7 +5792,7 @@ PHP_METHOD(Redis, subscribe) {
generic_subscribe_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, "subscribe");
}
-/**
+/**
* [p]unsubscribe channel_0 channel_1 ... channel_n
* [p]unsubscribe(array(channel_0, channel_1, ..., channel_n))
* response format :
@@ -5752,13 +5812,13 @@ PHP_REDIS_API void generic_unsubscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *u
RedisSock *redis_sock;
char *cmd = "", *old_cmd = NULL;
int cmd_len, array_count;
-
+
int i;
zval *z_tab, **z_channel;
-
- if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa",
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa",
&object, redis_ce, &array) == FAILURE) {
- RETURN_FALSE;
+ RETURN_FALSE;
}
if (redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) {
RETURN_FALSE;
@@ -5804,10 +5864,10 @@ PHP_REDIS_API void generic_unsubscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *u
while( i <= array_count) {
z_tab = redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
- if(Z_TYPE_P(z_tab) == IS_ARRAY) {
+ if(Z_TYPE_P(z_tab) == IS_ARRAY) {
if (zend_hash_index_find(Z_ARRVAL_P(z_tab), 1, (void**)&z_channel) == FAILURE) {
RETURN_FALSE;
- }
+ }
add_assoc_bool(return_value, Z_STRVAL_PP(z_channel), 1);
} else {
/*error */
@@ -6127,9 +6187,9 @@ PHP_METHOD(Redis, wait) {
int cmd_len;
/* Make sure arguments are valid */
- if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll",
+ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll",
&object, redis_ce, &num_slaves, &timeout)
- ==FAILURE)
+ ==FAILURE)
{
RETURN_FALSE;
}
@@ -6163,7 +6223,7 @@ redis_build_pubsub_cmd(RedisSock *redis_sock, char **ret, PUBSUB_TYPE type,
zval *arg TSRMLS_DC)
{
HashTable *ht_chan;
- HashPosition ptr;
+ HashPosition ptr;
zval **z_ele;
char *key;
int cmd_len, key_len, key_free;
@@ -6193,7 +6253,7 @@ redis_build_pubsub_cmd(RedisSock *redis_sock, char **ret, PUBSUB_TYPE type,
}
} else if(type == PUBSUB_NUMSUB) {
ht_chan = Z_ARRVAL_P(arg);
-
+
/* Add PUBSUB and NUMSUB bits */
redis_cmd_init_sstr(&cmd, zend_hash_num_elements(ht_chan)+1, "PUBSUB", sizeof("PUBSUB")-1);
redis_cmd_append_sstr(&cmd, "NUMSUB", sizeof("NUMSUB")-1);
@@ -6262,9 +6322,9 @@ PHP_METHOD(Redis, pubsub) {
zval *arg=NULL;
/* Parse arguments */
- if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|z",
+ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|z",
&object, redis_ce, &keyword, &kw_len, &arg)
- ==FAILURE)
+ ==FAILURE)
{
RETURN_FALSE;
}
@@ -6279,7 +6339,7 @@ PHP_METHOD(Redis, pubsub) {
} else if(!strncasecmp(keyword, "numsub", sizeof("numsub"))) {
/* One array argument */
if(ZEND_NUM_ARGS() < 2 || Z_TYPE_P(arg) != IS_ARRAY ||
- zend_hash_num_elements(Z_ARRVAL_P(arg))==0)
+ zend_hash_num_elements(Z_ARRVAL_P(arg))==0)
{
RETURN_FALSE;
}
@@ -6589,7 +6649,7 @@ PHP_METHOD(Redis, debug) {
char *cmd, *key;
int cmd_len, key_len, key_free;
- if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
+ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
&object, redis_ce, &key, &key_len)==FAILURE)
{
RETURN_FALSE;
@@ -6660,7 +6720,7 @@ PHP_METHOD(Redis, migrate) {
/* Parse arguments */
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oslsll|bb", &object, redis_ce,
- &host, &host_len, &port, &key, &key_len, &dest_db, &timeout,
+ &host, &host_len, &port, &key, &key_len, &dest_db, &timeout,
&copy, &replace) == FAILURE) {
RETURN_FALSE;
}
@@ -6675,19 +6735,19 @@ PHP_METHOD(Redis, migrate) {
/* Construct our command */
if(copy && replace) {
- cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsddss", host, host_len, port,
- key, key_len, dest_db, timeout, "COPY",
+ cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsddss", host, host_len, port,
+ key, key_len, dest_db, timeout, "COPY",
sizeof("COPY")-1, "REPLACE", sizeof("REPLACE")-1);
} else if(copy) {
cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsdds", host, host_len, port,
- key, key_len, dest_db, timeout, "COPY",
+ key, key_len, dest_db, timeout, "COPY",
sizeof("COPY")-1);
} else if(replace) {
cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsdds", host, host_len, port,
key, key_len, dest_db, timeout, "REPLACE",
sizeof("REPLACE")-1);
} else {
- cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsdd", host, host_len, port,
+ cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsdd", host, host_len, port,
key, key_len, dest_db, timeout);
}
@@ -7006,8 +7066,8 @@ PHP_METHOD(Redis, client) {
int cmd_len, opt_len, arg_len;
/* Parse our method parameters */
- if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|s",
- &object, redis_ce, &opt, &opt_len, &arg, &arg_len) == FAILURE)
+ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|s",
+ &object, redis_ce, &opt, &opt_len, &arg, &arg_len) == FAILURE)
{
RETURN_FALSE;
}
@@ -7020,7 +7080,7 @@ PHP_METHOD(Redis, client) {
/* Build our CLIENT command */
if(ZEND_NUM_ARGS() == 2) {
cmd_len = redis_cmd_format_static(&cmd, "CLIENT", "ss", opt, opt_len,
- arg, arg_len);
+ arg, arg_len);
} else {
cmd_len = redis_cmd_format_static(&cmd, "CLIENT", "s", opt, opt_len);
}
@@ -7207,8 +7267,8 @@ PHP_METHOD(Redis, zscan) {
generic_scan_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, TYPE_ZSCAN);
}
-/*
- * HyperLogLog based commands
+/*
+ * HyperLogLog based commands
*/
/* {{{ proto Redis::pfAdd(string key, array elements) }}} */
@@ -7278,7 +7338,7 @@ PHP_METHOD(Redis, pfadd) {
mem_len = Z_STRLEN_P(z_tmp);
}
}
-
+
// Append this member
redis_cmd_append_sstr(&cmd, mem, mem_len);
@@ -7291,12 +7351,12 @@ PHP_METHOD(Redis, pfadd) {
efree(mem);
}
}
-
- REDIS_PROCESS_REQUEST(redis_sock, cmd.c, cmd.len);
+
+ REDIS_PROCESS_REQUEST(redis_sock, cmd.c, cmd.len);
IF_ATOMIC() {
redis_1_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL);
}
- REDIS_PROCESS_RESPONSE(redis_1_response);
+ REDIS_PROCESS_RESPONSE(redis_1_response);
}
/* {{{ proto Redis::pfCount(string key) }}}*/
@@ -7330,7 +7390,7 @@ PHP_METHOD(Redis, pfcount) {
/* {{{ proto Redis::pfMerge(array keys) }}}*/
PHP_METHOD(Redis, pfmerge) {
- zval *object;
+ zval *object;
RedisSock *redis_sock;
zval *z_keys, **z_key;
HashTable *ht_keys;
diff --git a/tests/TestRedis.php b/tests/TestRedis.php
index 0d7c53f5..343e7984 100644
--- a/tests/TestRedis.php
+++ b/tests/TestRedis.php
@@ -88,7 +88,7 @@ class Redis_Test extends TestSuite
$this->assertTrue(is_array($result));
// PUBSUB NUMSUB
-
+
$c1 = uniqid() . '-' . rand(1,100);
$c2 = uniqid() . '-' . rand(1,100);
@@ -218,7 +218,7 @@ class Redis_Test extends TestSuite
$this->assertEquals('val', $this->redis->get('key2'));
$value = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-
+
$this->redis->set('key2', $value);
$this->assertEquals($value, $this->redis->get('key2'));
$this->assertEquals($value, $this->redis->get('key2'));
@@ -528,7 +528,7 @@ class Redis_Test extends TestSuite
}
$this->redis->delete('key');
-
+
$this->redis->set('key', 0);
$this->redis->incrbyfloat('key', 1.5);
@@ -1227,9 +1227,9 @@ class Redis_Test extends TestSuite
}
}
- //
+ //
// With and without count, while serializing
- //
+ //
$this->redis->delete('set0');
$this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
@@ -1253,11 +1253,11 @@ class Redis_Test extends TestSuite
public function testSRandMemberWithCount() {
// Make sure the set is nuked
$this->redis->delete('set0');
-
+
// Run with a count (positive and negative) on an empty set
$ret_pos = $this->redis->sRandMember('set0', 10);
$ret_neg = $this->redis->sRandMember('set0', -10);
-
+
// Should both be empty arrays
$this->assertTrue(is_array($ret_pos) && empty($ret_pos));
$this->assertTrue(is_array($ret_neg) && empty($ret_neg));
@@ -1845,10 +1845,10 @@ class Redis_Test extends TestSuite
// We should have found our connection
$this->assertFalse(empty($str_addr));
-
+
/* CLIENT GETNAME */
$this->assertTrue($this->redis->client('getname'), 'phpredis_unit_tests');
-
+
/* CLIENT KILL -- phpredis will reconnect, so we can do this */
$this->assertTrue($this->redis->client('kill', $str_addr));
}
@@ -2328,6 +2328,40 @@ class Redis_Test extends TestSuite
}
+ public function testZRangeByLex() {
+ /* Only out since 2.8.9 */
+ if (version_compare($this->version, '2.8.9', 'lt')) {
+ $this->markTestSkipped();
+ return;
+ }
+
+ $arr_vals = Array('a','b','c','d','e','f','g');
+
+ $this->redis->del('zlex');
+ foreach($arr_vals as $str_val) {
+ $this->redis->zadd('zlex', 0, $str_val);
+ }
+
+ /* These tests were taken off of redis.io out of sheer laziness :) */
+ $arr_ret = $this->redis->zRangeByLex('zlex', '-', '[c');
+ $this->assertTrue($arr_ret === Array('a','b','c'));
+
+ $arr_ret = $this->redis->zRangeByLex('zlex', '-', '(c');
+ $this->assertTrue($arr_ret === Array('a','b'));
+
+ $arr_ret = $this->redis->zRangeByLex('zlex', '[aaa', '(g');
+ $this->assertTrue($arr_ret === Array('b','c','d','e','f'));
+
+ /* Test with a limit and count */
+ $arr_ret = $this->redis->zRangeBylex('zlex', '-', '[c', 1, 2);
+ $this->assertTrue($arr_ret === Array('b','c'));
+
+ /* Test some invalid calls */
+ $this->assertFalse($this->redis->zRangeByLex('zlex','b','[s'));
+ $this->assertFalse($this->redis->zRangeByLex('zlex','(a', ''));
+ $this->assertFalse($this->redis->zRangeByLex('zlex','(a','[b',1));
+ }
+
public function testHashes() {
$this->redis->delete('h', 'key');
@@ -4496,9 +4530,9 @@ class Redis_Test extends TestSuite
public function testSerialize() {
$vals = Array(1, 1.5, 'one', Array('here','is','an','array'));
-
+
// Test with no serialization at all
- $this->assertTrue($this->redis->_serialize('test') === 'test');
+ $this->assertTrue($this->redis->_serialize('test') === 'test');
$this->assertTrue($this->redis->_serialize(1) === '1');
$this->assertTrue($this->redis->_serialize(Array()) === 'Array');
$this->assertTrue($this->redis->_serialize(new stdClass) === 'Object');
@@ -4509,7 +4543,7 @@ class Redis_Test extends TestSuite
}
foreach($arr_serializers as $mode) {
- $arr_enc = Array();
+ $arr_enc = Array();
$arr_dec = Array();
foreach($vals as $k => $v) {
@@ -4679,7 +4713,7 @@ class Redis_Test extends TestSuite
$this->markTestSkipped();
return;
}
-
+
// Never get empty sets
$this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY);
@@ -4688,7 +4722,7 @@ class Redis_Test extends TestSuite
for($i=0;$i<100;$i++) {
if($i>3) {
- $this->redis->hset('hash', "member:$i", "value:$i");
+ $this->redis->hset('hash', "member:$i", "value:$i");
} else {
$this->redis->hset('hash', "foomember:$i", "value:$i");
$i_foo_mems++;
@@ -4766,7 +4800,7 @@ class Redis_Test extends TestSuite
} else {
$this->redis->zadd('zset', $i, "mem:$i");
}
-
+
$i_tot_score += $i;
}
@@ -4877,7 +4911,7 @@ class Redis_Test extends TestSuite
// Clean up merge key
$this->redis->del('pf-merge-key');
-
+
// Merge the counters
$this->assertTrue($this->redis->pfmerge('pf-merge-key', $arr_keys));
@@ -4894,6 +4928,7 @@ class Redis_Test extends TestSuite
}
}
-exit(TestSuite::run("Redis_Test"));
+$str_test = isset($argv[1]) ? $argv[1] : NULL;
+exit(TestSuite::run("Redis_Test", $str_test));
?>
diff --git a/tests/test.php b/tests/test.php
index 6c714f1b..43d6a445 100644
--- a/tests/test.php
+++ b/tests/test.php
@@ -2,7 +2,6 @@
// phpunit is such a pain to install, we're going with pure-PHP here.
class TestSuite {
-
public static $errors = array();
public static $warnings = array();
@@ -47,16 +46,24 @@ class TestSuite {
throw new Exception($msg);
}
- public static function run($className) {
-
- $rc = new ReflectionClass($className);
+ public static function run($className, $str_limit) {
+ $rc = new ReflectionClass($className);
$methods = $rc->GetMethods(ReflectionMethod::IS_PUBLIC);
+ if ($str_limit) {
+ echo "Limiting to tests with the substring: '$str_limit'\n";
+ }
+
foreach($methods as $m) {
$name = $m->name;
if(substr($name, 0, 4) !== 'test')
continue;
+ /* If TestRedis.php was envoked with an argument, do a simple
+ * match against the routine. Useful to limit to one test */
+ if ($str_limit && strpos(strtolower($name),strtolower($str_limit))===false)
+ continue;
+
$count = count($className::$errors);
$rt = new $className;
try {