8000 Add getWithMeta method · phpredis/phpredis@9036ffc · GitHub
[go: up one dir, main page]

Skip to content

Commit 9036ffc

Browse files
committed
Add getWithMeta method
1 parent abb0f6c commit 9036ffc

16 files changed

+192
-56
lines changed

cluster_library.c

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,27 +1677,33 @@ PHP_REDIS_API void cluster_bulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster
16771677
void *ctx)
16781678
{
16791679
char *resp;
1680+
zval z_unpacked, z_ret, *zv;
16801681

16811682
// Make sure we can read the response
1682-
if (c->reply_type != TYPE_BULK ||
1683-
(resp = redis_sock_read_bulk_reply(c->cmd_sock, c->reply_len)) == NULL)
1684-
{
1685-
CLUSTER_RETURN_FALSE(c);
1683+
if (c->reply_type != TYPE_BULK) {
1684+
ZVAL_FALSE(&z_unpacked);
1685+
c->reply_len = 0;
1686+
} else if ((resp = redis_sock_read_bulk_reply(c->cmd_sock, c->reply_len)) == NULL) {
1687+
ZVAL_FALSE(&z_unpacked);
1688+
} else {
1689+
if (!redis_unpack(c->flags, resp, c->reply_len, &z_unpacked)) {
1690+
ZVAL_STRINGL_FAST(&z_unpacked, resp, c->reply_len);
1691+
}
1692+
efree(resp);
1693+
}
1694+
1695+
if (c->flags->flags & PHPREDIS_WITH_METADATA) {
1696+
redis_with_metadata(&z_ret, &z_unpacked, c->reply_len);
1697+
zv = &z_ret;
1698+
} else {
1699+
zv = &z_unpacked;
16861700
}
16871701

16881702
if (CLUSTER_IS_ATOMIC(c)) {
1689-
if (!redis_unpack(c->flags, resp, c->reply_len, return_value)) {
1690-
CLUSTER_RETURN_STRING(c, resp< A935 /span>, c->reply_len);
1691-
}
1703+
RETVAL_ZVAL(zv, 0, 1);
16921704
} else {
1693-
zval z_unpacked;
1694-
if (redis_unpack(c->flags, resp, c->reply_len, &z_unpacked)) {
1695-
add_next_index_zval(&c->multi_resp, &z_unpacked);
1696-
} else {
1697-
add_next_index_stringl(&c->multi_resp, resp, c->reply_len);
1698-
}
1705+
add_next_index_zval(&c->multi_resp, zv);
16991706
}
1700-
efree(resp);
17011707
}
17021708

17031709
/* Bulk response where we expect a double */
@@ -2553,8 +2559,9 @@ PHP_REDIS_API void cluster_multi_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS,
25532559
redisCluster *c, void *ctx)
25542560
{
25552561
zval *multi_resp = &c->multi_resp;
2556-
array_init(multi_resp);
2562+
uint8_t flags = c->flags->flags;
25572563

2564+
array_init(multi_resp);
25582565
clusterFoldItem *fi = c->multi_head;
25592566
while (fi) {
25602567
/* Make sure our transaction didn't fail here */
@@ -2570,7 +2577,9 @@ PHP_REDIS_API void cluster_multi_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS,
25702577
RETURN_FALSE;
25712578
}
25722579

2580+
c->flags->flags = fi->flags;
25732581
fi->callback(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, fi->ctx);
2582+
c->flags->flags = flags;
25742583
} else {
25752584
/* Just add false */
25762585
add_next_index_bool(multi_resp, 0);

cluster_library.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ struct clusterFoldItem {
264264

265265
/* Next item in our list */
266266
struct clusterFoldItem *next;
267+
268+
uint8_t flags;
267269
};
268270

269271
/* Key and value container, with info if they need freeing */

common.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ typedef enum {
152152
#define PIPELINE 2
153153

154154
#define PHPREDIS_DEBUG_LOGGING 0
155+
#define PHPREDIS_WITH_METADATA 1
155156

156157
#if PHP_VERSION_ID < 80000
157158
#define Z_PARAM_ARRAY_HT_OR_NULL(dest) \
@@ -184,6 +185,7 @@ typedef enum {
184185
#define REDIS_SAVE_CALLBACK(callback, closure_context) do { \
185186
fold_item *fi = redis_add_reply_callback(redis_sock); \
186187
fi->fun = callback; \
188+
fi->flags = redis_sock->flags; \
187189
fi->ctx = closure_context; \
188190
} while (0)
189191

@@ -266,6 +268,9 @@ static inline int redis_strncmp(const char *s1, const char *s2, size_t n) {
266268
#define REDIS_ENABLE_MODE(redis_sock, m) (redis_sock->mode |= m)
267269
#define REDIS_DISABLE_MODE(redis_sock, m) (redis_sock->mode &= ~m)
268270

271+
#define REDIS_ENABLE_FLAG(redis_sock, f) (redis_sock->flags |= f)
272+
#define REDIS_DISABLE_FLAG(redis_sock, f) (redis_sock->flags &= ~f)
273+
269274
/* HOST_NAME_MAX doesn't exist everywhere */
270275
#ifndef HOST_NAME_MAX
271276
#if defined(_POSIX_HOST_NAME_MAX)
@@ -325,6 +330,7 @@ typedef struct {
325330
int sentinel;
326331
size_t txBytes;
327332
size_t rxBytes;
333+
uint8_t flags;
328334
} RedisSock;
329335
/* }}} */
330336

@@ -334,6 +340,7 @@ typedef int (*FailableResultCallback)(INTERNAL_FUNCTION_PARAMETERS, RedisSock*,
334340

335341
typedef struct fold_item {
336342
FailableResultCallback fun;
343+
uint8_t flags;
337344
void *ctx;
338345
} fold_item;
339346

library.c

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,32 +2669,34 @@ PHP_REDIS_API int redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock
26692669

26702670
char *response;
26712671
int response_len;
2672+
zval z_unpacked, z_ret, *zv;
2673+
zend_bool ret;
26722674

2673-
if ((response = redis_sock_read(redis_sock, &response_len))
2674-
== NULL)
2675-
{
2676-
if (IS_ATOMIC(redis_sock)) {
2677-
RETVAL_FALSE;
2678-
} else {
2679-
add_next_index_bool(z_tab, 0);
2675+
if ((response = redis_sock_read(redis_sock, &response_len)) == NULL) {
2676+
ZVAL_FALSE(&z_unpacked);
2677+
ret = FAILURE;
2678+
} else {
2679+
if (!redis_unpack(redis_sock, response, response_len, &z_unpacked)) {
2680+
ZVAL_STRINGL_FAST(&z_unpacked, response, response_len);
26802681
}
2681-
return FAILURE;
2682+
efree(response);
2683+
ret = SUCCESS;
2684+
}
2685+
2686+
if (redis_sock->flags & PHPREDIS_WITH_METADATA) {
2687+
redis_with_metadata(&z_ret, &z_unpacked, response_len);
2688+
zv = &z_ret;
2689+
} else {
2690+
zv = &z_unpacked;
26822691
}
2692+
26832693
if (IS_ATOMIC(redis_sock)) {
2684-
if (!redis_unpack(redis_sock, response, response_len, return_value)) {
2685-
RETVAL_STRINGL_FAST(response, response_len);
2686-
}
2694+
RETVAL_ZVAL(zv, 0, 1);
26872695
} else {
2688-
zval z_unpacked;
2689-
if (redis_unpack(redis_sock, response, response_len, &z_unpacked)) {
2690-
add_next_index_zval(z_tab, &z_unpacked);
2691-
} else {
2692-
redis_add_next_index_stringl(z_tab, response, response_len);
2693-
}
2696+
add_next_index_zval(z_tab, zv);
26942697
}
26952698

2696-
efree(response);
2697-
return SUCCESS;
2699+
return ret;
26982700
}
26992701

27002702
/* like string response, but never unserialized. */
@@ -4455,6 +4457,17 @@ int redis_extract_auth_info(zval *ztest, zend_string **user, zend_string **pass)
44554457
return FAILURE;
44564458
}
44574459

4460+
PHP_REDIS_API void redis_with_metadata(zval *zdst, zval *zsrc, zend_long length) {
4461+
zval z_sub;
4462+
4463+
array_init(zdst);
4464+
add_next_index_zval(zdst, zsrc);
4465+
4466+
array_init(&z_sub);
4467+
add_assoc_long_ex(&z_sub, ZEND_STRL("length"), length);
4468+
add_next_index_zval(zdst, &z_sub);
4469+
}
4470+
44584471
/* Helper methods to extract configuration settings from a hash table */
44594472

44604473
zval *redis_hash_str_find_type(HashTable *ht, const char *key, int keylen, int type) {

library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ fold_item* redis_add_reply_callback(RedisSock *redis_sock);
4444
void redis_free_reply_callbacks(RedisSock *redis_sock);
4545

4646
PHP_REDIS_API int redis_extract_auth_info(zval *ztest, zend_string **user, zend_string **pass);
47+
PHP_REDIS_API void redis_with_metadata(zval *zdst, zval *zsrc, zend_long length);
4748

4849
int redis_cmd_init_sstr(smart_string *str, int num_args, char *keyword, int keyword_len);
4950
int redis_cmd_append_sstr(smart_string *str, char *append, int append_len);

redis.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -760,11 +760,32 @@ PHP_METHOD(Redis, reset)
760760
}
761761
/* }}} */
762762

763+
static void
764+
redis_get_passthru(INTERNAL_FUNCTION_PARAMETERS)
765+
{
766+
REDIS_PROCESS_KW_CMD("GET", redis_key_cmd, redis_string_response);
767+
}
768+
763769
/* {{{ proto string Redis::get(string key)
764770
*/
765771
PHP_METHOD(Redis, get)
766772
{
767-
REDIS_PROCESS_KW_CMD("GET", redis_key_cmd, redis_string_response);
773+
redis_get_passthru(INTERNAL_FUNCTION_PARAM_PASSTHRU);
774+
}
775+
/* }}} */
776+
777+
/* {{{ proto Redis|array|false Redis::getWithMeta(string key)
778+
*/
779+
PHP_METHOD(Redis, getWithMeta)
780+
{
781+
RedisSock *redis_sock;
782+
if ((redis_sock = redis_sock_get_instance(getThis(), 0)) == NULL) {
783+
RETURN_FALSE;
784+
}
785+
786+
REDIS_ENABLE_FLAG(redis_sock, PHPREDIS_WITH_METADATA);
787+
redis_get_passthru(INTERNAL_FUNCTION_PARAM_PASSTHRU);
788+
REDIS_DISABLE_FLAG(redis_sock, PHPREDIS_WITH_METADATA);
768789
}
769790
/* }}} */
770791

@@ -2067,13 +2088,17 @@ PHP_REDIS_API int
20672088
redis_sock_read_multibulk_multi_reply_loop(INTERNAL_FUNCTION_PARAMETERS,
20682089
RedisSock *redis_sock, zval *z_tab)
20692090
{
2070-
fold_item fi;
2091+
fold_item *fi;
2092+
uint8_t flags;
20712093
size_t i;
20722094

2095+
flags = redis_sock->flags;
20732096
for (i = 0; i < redis_sock->reply_callback_count; i++) {
2074-
fi = redis_sock->reply_callback[i];
2075-
if (fi.fun) {
2076-
fi.fun(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, fi.ctx);
2097+
fi = &redis_sock->reply_callback[i];
2098+
if (fi->fun) {
2099+
redis_sock->flags = fi->flags;
2100+
fi->fun(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, fi->ctx);
2101+
redis_sock->flags = flags;
20772102
continue;
20782103
}
20792104
size_t len;

redis.stub.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,16 @@ public function geosearchstore(string $dst, string $src, array|string $position,
14671467
*/
14681468
public function get(string $key): mixed;
14691469

1470+
/**
1471+
* Retrieve a value and metadata of key.
1472+
*
1473+
* @param string $key The key to query
1474+
* @return Redis|array|false
1475+
*
1476+
* @example $redis->getWithMeta('foo');
1477+
*/
1478+
public function getWithMeta(string $key): Redis|array|false;
1479+
14701480
/**
14711481
* Get the authentication information on the connection, if any.
14721482
*

redis_arginfo.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 3c4051fdd9f860523bcd72aba260b1af823d1d9c */
2+
* Stub hash: 6dd5a9e9d1d5ed8a78e248c99352232e30046f28 */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
55
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null")
@@ -323,6 +323,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_get, 0, 1, IS_MIXED,
323323
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
324324
ZEND_END_ARG_INFO()
325325

326+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_getWithMeta, 0, 1, Redis, MAY_BE_ARRAY|MAY_BE_FALSE)
327+
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
328+
ZEND_END_ARG_INFO()
329+
326330
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_getAuth, 0, 0, IS_MIXED, 0)
327331
ZEND_END_ARG_INFO()
328332

@@ -404,9 +408,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_hGet, 0, 2, IS_MIXED
404408
ZEND_ARG_TYPE_INFO(0, member, IS_STRING, 0)
405409
ZEND_END_ARG_INFO()
406410

407-
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hGetAll, 0, 1, Redis, MAY_BE_ARRAY|MAY_BE_FALSE)
408-
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
409-
ZEND_END_ARG_INFO()
411+
#define arginfo_class_Redis_hGetAll arginfo_class_Redis_getWithMeta
410412

411413
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hIncrBy, 0, 3, Redis, MAY_BE_LONG|MAY_BE_FALSE)
412414
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
@@ -420,7 +422,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hIncrByFloat, 0,
420422
ZEND_ARG_TYPE_INFO(0, value, IS_DOUBLE, 0)
421423
ZEND_END_ARG_INFO()
422424

423-
#define arginfo_class_Redis_hKeys arginfo_class_Redis_hGetAll
425+
#define arginfo_class_Redis_hKeys arginfo_class_Redis_getWithMeta
424426

425427
#define arginfo_class_Redis_hLen arginfo_class_Redis_expiretime
426428

@@ -455,7 +457,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hStrLen, 0, 2, R
455457
ZEND_ARG_TYPE_INFO(0, field, IS_STRING, 0)
456458
ZEND_END_ARG_INFO()
457459

458-
#define arginfo_class_Redis_hVals arginfo_class_Redis_hGetAll
460+
#define arginfo_class_Redis_hVals arginfo_class_Redis_getWithMeta
459461

460462
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hscan, 0, 2, Redis, MAY_BE_ARRAY|MAY_BE_BOOL)
461463
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
@@ -747,7 +749,7 @@ ZEND_END_ARG_INFO()
747749

748750
#define arginfo_class_Redis_sInterStore arginfo_class_Redis_del
749751

750-
#define arginfo_class_Redis_sMembers arginfo_class_Redis_hGetAll
752+
#define arginfo_class_Redis_sMembers arginfo_class_Redis_getWithMeta
751753

752754
#define arginfo_class_Redis_sMisMember arginfo_class_Redis_geohash
753755

@@ -1249,6 +1251,7 @@ ZEND_METHOD(Redis, georadiusbymember_ro);
12491251
ZEND_METHOD(Redis, geosearch);
12501252
ZEND_METHOD(Redis, geosearchstore);
12511253
ZEND_METHOD(Redis, get);
1254+
ZEND_METHOD(Redis, getWithMeta);
12521255
ZEND_METHOD(Redis, getAuth);
12531256
ZEND_METHOD(Redis, getBit);
12541257
ZEND_METHOD(Redis, getEx);
@@ -1507,6 +1510,7 @@ static const zend_function_entry class_Redis_methods[] = {
15071510
ZEND_ME(Redis, geosearch, arginfo_class_Redis_geosearch, ZEND_ACC_PUBLIC)
15081511
ZEND_ME(Redis, geosearchstore, arginfo_class_Redis_geosearchstore, ZEND_ACC_PUBLIC)
15091512
ZEND_ME(Redis, get, arginfo_class_Redis_get, ZEND_ACC_PUBLIC)
1513+
ZEND_ME(Redis, getWithMeta, arginfo_class_Redis_getWithMeta, ZEND_ACC_PUBLIC)
15101514
ZEND_ME(Redis, getAuth, arginfo_class_Redis_getAuth, ZEND_ACC_PUBLIC)
15111515
ZEND_ME(Redis, getBit, arginfo_class_Redis_getBit, ZEND_ACC_PUBLIC)
15121516
ZEND_ME(Redis, getEx, arginfo_class_Redis_getEx, ZEND_ACC_PUBLIC)

redis_cluster.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,12 +275,28 @@ PHP_METHOD(RedisCluster, close) {
275275
RETURN_TRUE;
276276
}
277277

278+
static void
279+
cluster_get_passthru(INTERNAL_FUNCTION_PARAMETERS)
280+
{
281+
CLUSTER_PROCESS_KW_CMD("GET", redis_key_cmd, cluster_bulk_resp, 1);
282+
}
283+
278284
/* {{{ proto string RedisCluster::get(string key) */
279285
PHP_METHOD(RedisCluster, get) {
280-
CLUSTER_PROCESS_KW_CMD("GET", redis_key_cmd, cluster_bulk_resp, 1);
286+
cluster_get_passthru(INTERNAL_FUNCTION_PARAM_PASSTHRU);
281287
}
282288
/* }}} */
283289

290+
/* {{{ proto array|false RedisCluster::getWithMeta(string key) */
291+
PHP_METHOD(RedisCluster, getWithMeta) {
292+
redisCluster *c = GET_CONTEXT();
293+
REDIS_ENABLE_FLAG(c->flags, PHPREDIS_WITH_METADATA);
294+
cluster_get_passthru(INTERNAL_FUNCTION_PARAM_PASSTHRU);
295+
REDIS_DISABLE_FLAG(c->flags, PHPREDIS_WITH_METADATA);
296+
}
297+
/* }}} */
298+
299+
284300
/* {{{ proto bool RedisCluster::set(string key, string value) */
285301
PHP_METHOD(RedisCluster, set) {
286302
CLUSTER_PROCESS_CMD(set, cluster_set_resp, 0);

redis_cluster.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
_item->slot = slot; \
2323
_item->ctx = ctx; \
2424
_item->next = NULL; \
25+
_item->flags = c->flags->flags; \
2526
if(c->multi_head == NULL) { \
2627
c->multi_head = _item; \
2728
c->multi_curr = _item; \

redis_cluster.stub.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,11 @@ public function geosearchstore(string $dst, string $src, array|string $position,
390390
*/
391391
public function get(string $key): mixed;
392392

393+
/**
394+
* @see Redis::getWithMeta
395+
*/
396+
public function getWithMeta(string $key): RedisCluster|array|false;
397+
393398
/**
394399
* @see Redis::getEx
395400
*/

0 commit comments

Comments
 (0)
0