diff options
author | Pavlo Yatsukhnenko <yatsukhnenko@gmail.com> | 2022-07-17 15:05:56 +0300 |
---|---|---|
committer | Pavlo Yatsukhnenko <yatsukhnenko@gmail.com> | 2022-08-03 22:28:08 +0300 |
commit | 687a5c788064534b82764db3cdba08ee38bad2de (patch) | |
tree | 02027e8b88d43ab51fe7552e82cf1b415d5b038a | |
parent | 8159048b589376d7661fd6aaff283a93e877f4c0 (diff) |
Issue #1943
Add lPos command.
-rw-r--r-- | library.c | 50 | ||||
-rw-r--r-- | library.h | 1 | ||||
-rw-r--r-- | redis.c | 7 | ||||
-rw-r--r-- | redis.stub.php | 6 | ||||
-rw-r--r-- | redis_arginfo.h | 20 | ||||
-rw-r--r-- | redis_commands.c | 63 | ||||
-rw-r--r-- | redis_commands.h | 3 | ||||
-rw-r--r-- | redis_legacy_arginfo.h | 20 | ||||
-rw-r--r-- | tests/RedisClusterTest.php | 1 | ||||
-rw-r--r-- | tests/RedisTest.php | 13 |
10 files changed, 170 insertions, 14 deletions
@@ -1335,6 +1335,56 @@ redis_pop_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_ } PHP_REDIS_API int +redis_lpos_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) +{ + char inbuf[4096]; + int i, numElems; + size_t len; + zval z_ret; + + if (redis_sock_gets(redis_sock, inbuf, sizeof(inbuf), &len) < 0) { + goto failure; + } + + if (ctx == NULL) { + if (*inbuf != TYPE_INT && *inbuf != TYPE_BULK) { + goto failure; + } + ZVAL_LONG(&z_ret, atol(inbuf + 1)); + } else if (ctx == PHPREDIS_CTX_PTR) { + if (*inbuf != TYPE_MULTIBULK) { + goto failure; + } + array_init(&z_ret); + numElems = atol(inbuf + 1); + for (i = 0; i < numElems; ++i) { + if (redis_sock_gets(redis_sock, inbuf, sizeof(inbuf), &len) < 0) { + zval_dtor(&z_ret); + goto failure; + } + add_next_index_long(&z_ret, atol(inbuf + 1)); + } + } else { + ZEND_ASSERT(!"memory corruption?"); + } + + if (IS_ATOMIC(redis_sock)) { + RETVAL_ZVAL(&z_ret, 0, 1); + } else { + add_next_index_zval(z_tab, &z_ret); + } + return SUCCESS; + +failure: + if (IS_ATOMIC(redis_sock)) { + RETVAL_FALSE; + } else { + add_next_index_bool(z_tab, 0); + } + return FAILURE; +} + +PHP_REDIS_API int redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx, SuccessCallback success_callback) @@ -168,6 +168,7 @@ PHP_REDIS_API int redis_set_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *re PHP_REDIS_API int redis_geosearch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); PHP_REDIS_API int redis_hrandfield_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); PHP_REDIS_API int redis_pop_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API int redis_lpos_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); /* Helper methods to get configuration values from a HashTable. */ @@ -1253,6 +1253,13 @@ PHP_METHOD(Redis, lPop) } /* }}} */ +/* {{{ proto string Redis::lPos(string key, mixed value, [array options = null]) */ +PHP_METHOD(Redis, lPos) +{ + REDIS_PROCESS_CMD(lpos, redis_lpos_response); +} +/* }}} */ + /* {{{ proto string Redis::rPop(string key, [int count = 0]) */ PHP_METHOD(Redis, rPop) { diff --git a/redis.stub.php b/redis.stub.php index 0b7e1776..16b6164c 100644 --- a/redis.stub.php +++ b/redis.stub.php @@ -10,10 +10,10 @@ class Redis { public function __construct(array $options = null); - public function _compress(string $value): string; - public function __destruct(); + public function _compress(string $value): string; + public function _pack(mixed $value): string; public function _prefix(string $key): string; @@ -241,6 +241,8 @@ class Redis { public function lPop(string $key, int $count = 0): bool|string|array; + public function lPos(string $key, mixed $value, array $options = null): bool|int|array; + /** * @param mixed $elements * @return int|Redis diff --git a/redis_arginfo.h b/redis_arginfo.h index 74cde5dc..b5f67ad0 100644 --- a/redis_arginfo.h +++ b/redis_arginfo.h @@ -1,15 +1,15 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 954ed131a20d6939f9653dbc384e6244a0862b6e */ + * Stub hash: 7fc0b991dc8404945a0081aef8a422c9c670eab9 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis__compress, 0, 1, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___destruct, 0, 0, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___destruct, 0, 0, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis__compress, 0, 1, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis__pack, 0, 1, IS_STRING, 0) @@ -416,6 +416,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Redis_lPop, 0, 1, MAY_BE_B ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, count, IS_LONG, 0, "0") ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Redis_lPos, 0, 2, MAY_BE_BOOL|MAY_BE_LONG|MAY_BE_ARRAY) + ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null") +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_lPush, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_VARIADIC_INFO(0, elements) @@ -975,8 +981,8 @@ ZEND_END_ARG_INFO() ZEND_METHOD(Redis, __construct); -ZEND_METHOD(Redis, _compress); ZEND_METHOD(Redis, __destruct); +ZEND_METHOD(Redis, _compress); ZEND_METHOD(Redis, _pack); ZEND_METHOD(Redis, _prefix); ZEND_METHOD(Redis, _serialize); @@ -1072,6 +1078,7 @@ ZEND_METHOD(Redis, lInsert); ZEND_METHOD(Redis, lLen); ZEND_METHOD(Redis, lMove); ZEND_METHOD(Redis, lPop); +ZEND_METHOD(Redis, lPos); ZEND_METHOD(Redis, lPush); ZEND_METHOD(Redis, rPush); ZEND_METHOD(Redis, lPushx); @@ -1205,8 +1212,8 @@ ZEND_METHOD(Redis, zunionstore); static const zend_function_entry class_Redis_methods[] = { ZEND_ME(Redis, __construct, arginfo_class_Redis___construct, ZEND_ACC_PUBLIC) - ZEND_ME(Redis, _compress, arginfo_class_Redis__compress, ZEND_ACC_PUBLIC) ZEND_ME(Redis, __destruct, arginfo_class_Redis___destruct, ZEND_ACC_PUBLIC) + ZEND_ME(Redis, _compress, arginfo_class_Redis__compress, ZEND_ACC_PUBLIC) ZEND_ME(Redis, _pack, arginfo_class_Redis__pack, ZEND_ACC_PUBLIC) ZEND_ME(Redis, _prefix, arginfo_class_Redis__prefix, ZEND_ACC_PUBLIC) ZEND_ME(Redis, _serialize, arginfo_class_Redis__serialize, ZEND_ACC_PUBLIC) @@ -1303,6 +1310,7 @@ static const zend_function_entry class_Redis_methods[] = { ZEND_ME(Redis, lLen, arginfo_class_Redis_lLen, ZEND_ACC_PUBLIC) ZEND_ME(Redis, lMove, arginfo_class_Redis_lMove, ZEND_ACC_PUBLIC) ZEND_ME(Redis, lPop, arginfo_class_Redis_lPop, ZEND_ACC_PUBLIC) + ZEND_ME(Redis, lPos, arginfo_class_Redis_lPos, ZEND_ACC_PUBLIC) ZEND_ME(Redis, lPush, arginfo_class_Redis_lPush, ZEND_ACC_PUBLIC) ZEND_ME(Redis, rPush, arginfo_class_Redis_rPush, ZEND_ACC_PUBLIC) ZEND_ME(Redis, lPushx, arginfo_class_Redis_lPushx, ZEND_ACC_PUBLIC) diff --git a/redis_commands.c b/redis_commands.c index f85a764b..ea1eedc7 100644 --- a/redis_commands.c +++ b/redis_commands.c @@ -2626,6 +2626,69 @@ int redis_lrem_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, return SUCCESS; } +int +redis_lpos_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, + char **cmd, int *cmd_len, short *slot, void **ctx) +{ + char *key; + int argc = 2; + size_t key_len; + smart_string cmdstr = {0}; + zend_bool withrank = 0; + zend_long rank = 0, count = -1, maxlen = -1; + zend_string *zkey; + zval *z_val, *z_ele, *z_opts = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz|a", + &key, &key_len, &z_val, &z_opts) == FAILURE) + { + return FAILURE; + } + + if (z_opts != NULL) { + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(z_opts), zkey, z_ele) { + if (zkey != NULL) { + ZVAL_DEREF(z_ele); + if (zend_string_equals_literal_ci(zkey, "count")) { + count = zval_get_long(z_ele); + } else if (zend_string_equals_literal_ci(zkey, "maxlen")) { + maxlen = zval_get_long(z_ele); + } else if (zend_string_equals_literal_ci(zkey, "rank")) { + rank = zval_get_long(z_ele); + withrank = 1; + } + } + } ZEND_HASH_FOREACH_END(); + } + + argc += (withrank ? 2 : 0) + (count >= 0 ? 2 : 0) + (maxlen >= 0 ? 2 : 0); + REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, argc, "LPOS"); + + redis_cmd_append_sstr_key(&cmdstr, key, key_len, redis_sock, slot); + redis_cmd_append_sstr_zval(&cmdstr, z_val, redis_sock); + + if (withrank) { + REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "RANK"); + redis_cmd_append_sstr_long(&cmdstr, rank); + } + + if (count >= 0) { + REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "COUNT"); + redis_cmd_append_sstr_long(&cmdstr, count); + *ctx = PHPREDIS_CTX_PTR; + } + + if (maxlen >= 0) { + REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "MAXLEN"); + redis_cmd_append_sstr_long(&cmdstr, maxlen); + } + + *cmd = cmdstr.c; + *cmd_len = cmdstr.len; + + return SUCCESS; +} + int redis_smove_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char **cmd, int *cmd_len, short *slot, void **ctx) { diff --git a/redis_commands.h b/redis_commands.h index e766e20d..e412d828 100644 --- a/redis_commands.h +++ b/redis_commands.h @@ -229,6 +229,9 @@ int redis_linsert_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, int redis_lrem_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char **cmd, int *cmd_len, short *slot, void **ctx); +int redis_lpos_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, + char **cmd, int *cmd_len, short *slot, void **ctx); + int redis_smove_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char **cmd, int *cmd_len, short *slot, void **ctx); diff --git a/redis_legacy_arginfo.h b/redis_legacy_arginfo.h index 05645b02..5cced37a 100644 --- a/redis_legacy_arginfo.h +++ b/redis_legacy_arginfo.h @@ -1,15 +1,15 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 954ed131a20d6939f9653dbc384e6244a0862b6e */ + * Stub hash: 7fc0b991dc8404945a0081aef8a422c9c670eab9 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0) ZEND_ARG_INFO(0, options) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis__compress, 0, 0, 1) - ZEND_ARG_INFO(0, value) +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___destruct, 0, 0, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___destruct, 0, 0, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis__compress, 0, 0, 1) + ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() #define arginfo_class_Redis__pack arginfo_class_Redis__compress @@ -371,6 +371,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_lPop, 0, 0, 1) ZEND_ARG_INFO(0, count) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_lPos, 0, 0, 2) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_lPush, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_VARIADIC_INFO(0, elements) @@ -871,8 +877,8 @@ ZEND_END_ARG_INFO() ZEND_METHOD(Redis, __construct); -ZEND_METHOD(Redis, _compress); ZEND_METHOD(Redis, __destruct); +ZEND_METHOD(Redis, _compress); ZEND_METHOD(Redis, _pack); ZEND_METHOD(Redis, _prefix); ZEND_METHOD(Redis, _serialize); @@ -968,6 +974,7 @@ ZEND_METHOD(Redis, lInsert); ZEND_METHOD(Redis, lLen); ZEND_METHOD(Redis, lMove); ZEND_METHOD(Redis, lPop); +ZEND_METHOD(Redis, lPos); ZEND_METHOD(Redis, lPush); ZEND_METHOD(Redis, rPush); ZEND_METHOD(Redis, lPushx); @@ -1101,8 +1108,8 @@ ZEND_METHOD(Redis, zunionstore); static const zend_function_entry class_Redis_methods[] = { ZEND_ME(Redis, __construct, arginfo_class_Redis___construct, ZEND_ACC_PUBLIC) - ZEND_ME(Redis, _compress, arginfo_class_Redis__compress, ZEND_ACC_PUBLIC) ZEND_ME(Redis, __destruct, arginfo_class_Redis___destruct, ZEND_ACC_PUBLIC) + ZEND_ME(Redis, _compress, arginfo_class_Redis__compress, ZEND_ACC_PUBLIC) ZEND_ME(Redis, _pack, arginfo_class_Redis__pack, ZEND_ACC_PUBLIC) ZEND_ME(Redis, _prefix, arginfo_class_Redis__prefix, ZEND_ACC_PUBLIC) ZEND_ME(Redis, _serialize, arginfo_class_Redis__serialize, ZEND_ACC_PUBLIC) @@ -1199,6 +1206,7 @@ static const zend_function_entry class_Redis_methods[] = { ZEND_ME(Redis, lLen, arginfo_class_Redis_lLen, ZEND_ACC_PUBLIC) ZEND_ME(Redis, lMove, arginfo_class_Redis_lMove, ZEND_ACC_PUBLIC) ZEND_ME(Redis, lPop, arginfo_class_Redis_lPop, ZEND_ACC_PUBLIC) + ZEND_ME(Redis, lPos, arginfo_class_Redis_lPos, ZEND_ACC_PUBLIC) ZEND_ME(Redis, lPush, arginfo_class_Redis_lPush, ZEND_ACC_PUBLIC) ZEND_ME(Redis, rPush, arginfo_class_Redis_rPush, ZEND_ACC_PUBLIC) ZEND_ME(Redis, lPushx, arginfo_class_Redis_lPushx, ZEND_ACC_PUBLIC) diff --git a/tests/RedisClusterTest.php b/tests/RedisClusterTest.php index 18e4ac21..6daa93bb 100644 --- a/tests/RedisClusterTest.php +++ b/tests/RedisClusterTest.php @@ -51,6 +51,7 @@ class Redis_Cluster_Test extends Redis_Test { public function testInvalidAuthArgs() { return $this->markTestSkipped(); } public function testlMove() { return $this->markTestSkipped(); } + public function testlPos() { return $this->marktestSkipped(); } public function testsMisMember() { return $this->markTestSkipped(); } public function testzDiff() { return $this->markTestSkipped(); } public function testzInter() { return $this->markTestSkipped(); } diff --git a/tests/RedisTest.php b/tests/RedisTest.php index 43a0cb1e..de76e9b4 100644 --- a/tests/RedisTest.php +++ b/tests/RedisTest.php @@ -1015,6 +1015,19 @@ class Redis_Test extends TestSuite $this->assertTrue($this->redis->lrange('key', 0, -1) === ['val2', 'val0', 'val1']); } + public function testlPos() + { + $this->redis->del('key'); + $this->redis->lPush('key', 'val0', 'val1', 'val1'); + $this->assertEquals(2, $this->redis->lPos('key', 'val0')); + $this->assertEquals(0, $this->redis->lPos('key', 'val1')); + $this->assertEquals(1, $this->redis->lPos('key', 'val1', ['rank' => 2])); + $this->assertEquals([0, 1], $this->redis->lPos('key', 'val1', ['count' => 2])); + $this->assertEquals([0], $this->redis->lPos('key', 'val1', ['count' => 2, 'maxlen' => 1])); + $this->assertEquals([], $this->redis->lPos('key', 'val2', ['count' => 1])); + $this->assertEquals(-1, $this->redis->lPos('key', 'val2')); + } + // ltrim, lsize, lpop public function testltrim() { |