mirror of
https://github.com/phpredis/phpredis.git
synced 2026-06-19 07:35:31 +00:00
@@ -1543,6 +1543,75 @@ redis_sock_read_single_line(RedisSock *redis_sock, char *buffer, size_t buflen,
|
||||
return type == TYPE_LINE ? 0 : -1;
|
||||
}
|
||||
|
||||
static int
|
||||
geosearch_cast(zval *zv)
|
||||
{
|
||||
if (Z_TYPE_P(zv) == IS_ARRAY) {
|
||||
zend_hash_apply(Z_ARRVAL_P(zv), geosearch_cast);
|
||||
} else if (Z_TYPE_P(zv) == IS_STRING) {
|
||||
convert_to_double(zv);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_geosearch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zval *z_tab, void *ctx)
|
||||
{
|
||||
int numElems;
|
||||
zval z_ret, z_multi_result, z_sub, z_tmp, *z_ele, *zv;
|
||||
zend_string *zkey;
|
||||
|
||||
if (read_mbulk_header(redis_sock, &numElems) < 0) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (numElems < 0 && redis_sock->null_mbulk_as_null) {
|
||||
ZVAL_NULL(&z_ret);
|
||||
} else {
|
||||
array_init(&z_ret);
|
||||
if (ctx == NULL) {
|
||||
redis_mbulk_reply_loop(redis_sock, &z_ret, numElems, UNSERIALIZE_NONE);
|
||||
} else {
|
||||
array_init(&z_multi_result);
|
||||
redis_read_multibulk_recursive(redis_sock, numElems, 0, &z_multi_result);
|
||||
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL(z_multi_result), z_ele) {
|
||||
// The first item in the sub-array is always the name of the returned item
|
||||
zv = zend_hash_index_find(Z_ARRVAL_P(z_ele), 0);
|
||||
zkey = zval_get_string(zv);
|
||||
|
||||
zend_hash_index_del(Z_ARRVAL_P(z_ele), 0);
|
||||
|
||||
// The other information is returned in the following order as successive
|
||||
// elements of the sub-array: distance, geohash, coordinates
|
||||
zend_hash_apply(Z_ARRVAL_P(z_ele), geosearch_cast);
|
||||
|
||||
// Copy values to re-order from zero
|
||||
array_init(&z_sub);
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_ele), zv) {
|
||||
ZVAL_ZVAL(&z_tmp, zv, 1, 0);
|
||||
add_next_index_zval(&z_sub, &z_tmp);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
add_assoc_zval_ex(&z_ret, ZSTR_VAL(zkey), ZSTR_LEN(zkey), &z_sub);
|
||||
zend_string_release(zkey);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
// Cleanup
|
||||
zval_dtor(&z_multi_result);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ATOMIC(redis_sock)) {
|
||||
RETVAL_ZVAL(&z_ret, 0, 1);
|
||||
} else {
|
||||
add_next_index_zval(z_tab, &z_ret);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* Helper function to consume Redis stream message data. This is useful for
|
||||
* multiple stream callers (e.g. XREAD[GROUP], and X[REV]RANGE handlers). */
|
||||
PHP_REDIS_API int
|
||||
|
||||
@@ -165,6 +165,7 @@ PHP_REDIS_API int redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSoc
|
||||
PHP_REDIS_API int redis_zrandmember_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_zdiff_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_set_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_geosearch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
|
||||
/* Helper methods to get configuration values from a HashTable. */
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
#define PHP_REDIS_H
|
||||
|
||||
/* phpredis version */
|
||||
#define PHP_REDIS_VERSION "5.3.2"
|
||||
#define PHP_REDIS_VERSION "6.0.0-dev"
|
||||
|
||||
/* For convenience we store the salt as a printable hex string which requires 2
|
||||
* characters per byte + 1 for the NULL terminator */
|
||||
|
||||
@@ -3598,6 +3598,14 @@ PHP_METHOD(Redis, georadiusbymember_ro) {
|
||||
REDIS_PROCESS_KW_CMD("GEORADIUSBYMEMBER_RO", redis_georadiusbymember_cmd, redis_read_variant_reply);
|
||||
}
|
||||
|
||||
PHP_METHOD(Redis, geosearch) {
|
||||
REDIS_PROCESS_CMD(geosearch, redis_geosearch_response);
|
||||
}
|
||||
|
||||
PHP_METHOD(Redis, geosearchstore) {
|
||||
REDIS_PROCESS_CMD(geosearchstore, redis_long_response);
|
||||
}
|
||||
|
||||
/*
|
||||
* Streams
|
||||
*/
|
||||
|
||||
@@ -137,6 +137,10 @@ class Redis {
|
||||
|
||||
public function georadiusbymember_ro(string $key, string $member, float $radius, string $unit, array $options = []): array;
|
||||
|
||||
public function geosearch(string $key, array|string $position, array|int|float $shape, string $unit, array $options = []): array;
|
||||
|
||||
public function geosearchstore(string $dst, string $src, array|string $position, array|int|float $shape, string $unit, array $options = []): array;
|
||||
|
||||
/** @return string|Redis */
|
||||
public function get(string $key);
|
||||
|
||||
|
||||
+22
-1
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 1c4a88252c8b66263f1b1d72af974ba5ce992d40 */
|
||||
* Stub hash: c2cbe49e22cba6f23e98c1676b7769c55a6fd043 */
|
||||
|
||||
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")
|
||||
@@ -229,6 +229,23 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_Redis_georadiusbymember_ro arginfo_class_Redis_georadiusbymember
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_geosearch, 0, 4, IS_ARRAY, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_MASK(0, position, MAY_BE_ARRAY|MAY_BE_STRING, NULL)
|
||||
ZEND_ARG_TYPE_MASK(0, shape, MAY_BE_ARRAY|MAY_BE_LONG|MAY_BE_DOUBLE, NULL)
|
||||
ZEND_ARG_TYPE_INFO(0, unit, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_geosearchstore, 0, 5, IS_ARRAY, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, dst, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, src, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_MASK(0, position, MAY_BE_ARRAY|MAY_BE_STRING, NULL)
|
||||
ZEND_ARG_TYPE_MASK(0, shape, MAY_BE_ARRAY|MAY_BE_LONG|MAY_BE_DOUBLE, NULL)
|
||||
ZEND_ARG_TYPE_INFO(0, unit, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_Redis_get arginfo_class_Redis_decr
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_getAuth, 0, 0, IS_MIXED, 0)
|
||||
@@ -974,6 +991,8 @@ ZEND_METHOD(Redis, georadius);
|
||||
ZEND_METHOD(Redis, georadius_ro);
|
||||
ZEND_METHOD(Redis, georadiusbymember);
|
||||
ZEND_METHOD(Redis, georadiusbymember_ro);
|
||||
ZEND_METHOD(Redis, geosearch);
|
||||
ZEND_METHOD(Redis, geosearchstore);
|
||||
ZEND_METHOD(Redis, get);
|
||||
ZEND_METHOD(Redis, getAuth);
|
||||
ZEND_METHOD(Redis, getBit);
|
||||
@@ -1197,6 +1216,8 @@ static const zend_function_entry class_Redis_methods[] = {
|
||||
ZEND_ME(Redis, georadius_ro, arginfo_class_Redis_georadius_ro, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, georadiusbymember, arginfo_class_Redis_georadiusbymember, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, georadiusbymember_ro, arginfo_class_Redis_georadiusbymember_ro, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, geosearch, arginfo_class_Redis_geosearch, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, geosearchstore, arginfo_class_Redis_geosearchstore, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, get, arginfo_class_Redis_get, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, getAuth, arginfo_class_Redis_getAuth, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, getBit, arginfo_class_Redis_getBit, ZEND_ACC_PUBLIC)
|
||||
|
||||
@@ -3316,6 +3316,248 @@ int redis_georadiusbymember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
redis_geosearch_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx)
|
||||
{
|
||||
char *key, *unit;
|
||||
int argc = 2;
|
||||
short store_slot = 0;
|
||||
size_t keylen, unitlen;
|
||||
geoOptions gopts = {0};
|
||||
smart_string cmdstr = {0};
|
||||
zval *position, *shape, *opts = NULL, *z_ele;
|
||||
zend_string *zkey;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "szzs|a",
|
||||
&key, &keylen, &position, &shape,
|
||||
&unit, &unitlen, &opts) == FAILURE)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(position) == IS_STRING && Z_STRLEN_P(position) > 0) {
|
||||
argc += 2;
|
||||
} else if (Z_TYPE_P(position) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(position)) == 2) {
|
||||
argc += 3;
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "Invalid position");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(shape) == IS_LONG || Z_TYPE_P(shape) == IS_DOUBLE) {
|
||||
argc += 2;
|
||||
} else if (Z_TYPE_P(shape) == IS_ARRAY) {
|
||||
argc += 3;
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "Invalid shape dimensions");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Attempt to parse our options array */
|
||||
if (opts != NULL && Z_TYPE_P(opts) == IS_ARRAY) {
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(opts), zkey, z_ele) {
|
||||
ZVAL_DEREF(z_ele);
|
||||
if (zkey != NULL) {
|
||||
if (zend_string_equals_literal_ci(zkey, "COUNT")) {
|
||||
if (Z_TYPE_P(z_ele) != IS_LONG || Z_LVAL_P(z_ele) <= 0) {
|
||||
php_error_docref(NULL, E_WARNING, "COUNT must be an integer > 0!");
|
||||
return FAILURE;
|
||||
}
|
||||
gopts.count = Z_LVAL_P(z_ele);
|
||||
}
|
||||
} else if (Z_TYPE_P(z_ele) == IS_STRING) {
|
||||
if (!strcasecmp(Z_STRVAL_P(z_ele), "WITHCOORD")) {
|
||||
gopts.withcoord = 1;
|
||||
} else if (!strcasecmp(Z_STRVAL_P(z_ele), "WITHDIST")) {
|
||||
gopts.withdist = 1;
|
||||
} else if (!strcasecmp(Z_STRVAL_P(z_ele), "WITHHASH")) {
|
||||
gopts.withhash = 1;
|
||||
} else if (!strcasecmp(Z_STRVAL_P(z_ele), "ASC")) {
|
||||
gopts.sort = SORT_ASC;
|
||||
} else if (!strcasecmp(Z_STRVAL_P(z_ele), "DESC")) {
|
||||
gopts.sort = SORT_DESC;
|
||||
}
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
|
||||
/* Increment argc based on options */
|
||||
argc += gopts.withcoord + gopts.withdist + gopts.withhash
|
||||
+ (gopts.sort != SORT_NONE) + (gopts.count ? 2 : 0);
|
||||
|
||||
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, argc, "GEOSEARCH");
|
||||
redis_cmd_append_sstr_key(&cmdstr, key, keylen, redis_sock, slot);
|
||||
|
||||
if (Z_TYPE_P(position) == IS_ARRAY) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "FROMLONLAT");
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(position), z_ele) {
|
||||
ZVAL_DEREF(z_ele);
|
||||
redis_cmd_append_sstr_dbl(&cmdstr, zval_get_double(z_ele));
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} else {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "FROMMEMBER");
|
||||
redis_cmd_append_sstr(&cmdstr, Z_STRVAL_P(position), Z_STRLEN_P(position));
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(shape) == IS_ARRAY) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "BYBOX");
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(shape), z_ele) {
|
||||
ZVAL_DEREF(z_ele);
|
||||
redis_cmd_append_sstr_dbl(&cmdstr, zval_get_double(z_ele));
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} else {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "BYRADIUS");
|
||||
redis_cmd_append_sstr_dbl(&cmdstr, zval_get_double(shape));
|
||||
}
|
||||
redis_cmd_append_sstr(&cmdstr, unit, unitlen);
|
||||
|
||||
/* Append optional arguments */
|
||||
if (gopts.withcoord) REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "WITHCOORD");
|
||||
if (gopts.withdist) REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "WITHDIST");
|
||||
if (gopts.withhash) REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "WITHHASH");
|
||||
|
||||
/* Append sort if it's not GEO_NONE */
|
||||
if (gopts.sort == SORT_ASC) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "ASC");
|
||||
} else if (gopts.sort == SORT_DESC) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "DESC");
|
||||
}
|
||||
|
||||
/* Append our count if we've got one */
|
||||
if (gopts.count) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "COUNT");
|
||||
redis_cmd_append_sstr_long(&cmdstr, gopts.count);
|
||||
}
|
||||
|
||||
if ((argc = gopts.withcoord + gopts.withdist + gopts.withhash) > 0) {
|
||||
*ctx = PHPREDIS_CTX_PTR;
|
||||
}
|
||||
|
||||
*cmd = cmdstr.c;
|
||||
*cmd_len = cmdstr.len;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
redis_geosearchstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx)
|
||||
{
|
||||
int argc = 3;
|
||||
char *dest, *src, *unit;
|
||||
short store_slot = 0;
|
||||
size_t destlen, srclen, unitlen;
|
||||
geoOptions gopts = {0};
|
||||
smart_string cmdstr = {0};
|
||||
zval *position, *shape, *opts = NULL, *z_ele;
|
||||
zend_string *zkey;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sszzs|a",
|
||||
&dest, &destlen, &src, &srclen, &position, &shape,
|
||||
&unit, &unitlen, &opts) == FAILURE)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(position) == IS_STRING && Z_STRLEN_P(position) > 0) {
|
||||
argc += 2;
|
||||
} else if (Z_TYPE_P(position) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(position)) == 2) {
|
||||
argc += 3;
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "Invalid position");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(shape) == IS_LONG || Z_TYPE_P(shape) == IS_DOUBLE) {
|
||||
argc += 2;
|
||||
} else if (Z_TYPE_P(shape) == IS_ARRAY) {
|
||||
argc += 3;
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "Invalid shape dimensions");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Attempt to parse our options array */
|
||||
if (opts != NULL && Z_TYPE_P(opts) == IS_ARRAY) {
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(opts), zkey, z_ele) {
|
||||
ZVAL_DEREF(z_ele);
|
||||
if (zkey != NULL) {
|
||||
if (zend_string_equals_literal_ci(zkey, "COUNT")) {
|
||||
if (Z_TYPE_P(z_ele) != IS_LONG || Z_LVAL_P(z_ele) <= 0) {
|
||||
php_error_docref(NULL, E_WARNING, "COUNT must be an integer > 0!");
|
||||
return FAILURE;
|
||||
}
|
||||
gopts.count = Z_LVAL_P(z_ele);
|
||||
}
|
||||
} else if (Z_TYPE_P(z_ele) == IS_STRING) {
|
||||
if (!strcasecmp(Z_STRVAL_P(z_ele), "ASC")) {
|
||||
gopts.sort = SORT_ASC;
|
||||
} else if (!strcasecmp(Z_STRVAL_P(z_ele), "DESC")) {
|
||||
gopts.sort = SORT_DESC;
|
||||
} else if (!strcasecmp(Z_STRVAL_P(z_ele), "STOREDIST")) {
|
||||
gopts.store = STORE_DIST;
|
||||
}
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
}
|
||||
|
||||
/* Increment argc based on options */
|
||||
argc += gopts.withcoord + gopts.withdist + gopts.withhash
|
||||
+ (gopts.sort != SORT_NONE) + (gopts.count ? 2 : 0)
|
||||
+ (gopts.store != STORE_NONE);
|
||||
|
||||
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, argc, "GEOSEARCHSTORE");
|
||||
redis_cmd_append_sstr_key(&cmdstr, dest, destlen, redis_sock, slot);
|
||||
redis_cmd_append_sstr_key(&cmdstr, src, srclen, redis_sock, slot);
|
||||
|
||||
if (Z_TYPE_P(position) == IS_ARRAY) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "FROMLONLAT");
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(position), z_ele) {
|
||||
ZVAL_DEREF(z_ele);
|
||||
redis_cmd_append_sstr_dbl(&cmdstr, zval_get_double(z_ele));
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} else {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "FROMMEMBER");
|
||||
redis_cmd_append_sstr(&cmdstr, Z_STRVAL_P(position), Z_STRLEN_P(position));
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(shape) == IS_ARRAY) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "BYBOX");
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(shape), z_ele) {
|
||||
ZVAL_DEREF(z_ele);
|
||||
redis_cmd_append_sstr_dbl(&cmdstr, zval_get_double(z_ele));
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} else {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "BYRADIUS");
|
||||
redis_cmd_append_sstr_dbl(&cmdstr, zval_get_double(shape));
|
||||
}
|
||||
redis_cmd_append_sstr(&cmdstr, unit, unitlen);
|
||||
|
||||
/* Append sort if it's not GEO_NONE */
|
||||
if (gopts.sort == SORT_ASC) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "ASC");
|
||||
} else if (gopts.sort == SORT_DESC) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "DESC");
|
||||
}
|
||||
|
||||
/* Append our count if we've got one */
|
||||
if (gopts.count) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "COUNT");
|
||||
redis_cmd_append_sstr_long(&cmdstr, gopts.count);
|
||||
}
|
||||
|
||||
if (gopts.store == STORE_DIST) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "STOREDIST");
|
||||
}
|
||||
|
||||
*cmd = cmdstr.c;
|
||||
*cmd_len = cmdstr.len;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* MIGRATE */
|
||||
int redis_migrate_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx)
|
||||
|
||||
@@ -145,6 +145,12 @@ int redis_georadius_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
int redis_georadiusbymember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_geosearch_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_geosearchstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
/* Commands which need a unique construction mechanism. This is either because
|
||||
* they don't share a signature with any other command, or because there is
|
||||
* specific processing we do (e.g. verifying subarguments) that make them
|
||||
|
||||
+22
-1
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 1c4a88252c8b66263f1b1d72af974ba5ce992d40 */
|
||||
* Stub hash: c2cbe49e22cba6f23e98c1676b7769c55a6fd043 */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
|
||||
ZEND_ARG_INFO(0, options)
|
||||
@@ -217,6 +217,23 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_Redis_georadiusbymember_ro arginfo_class_Redis_georadiusbymember
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_geosearch, 0, 0, 4)
|
||||
ZEND_ARG_INFO(0, key)
|
||||
ZEND_ARG_INFO(0, position)
|
||||
ZEND_ARG_INFO(0, shape)
|
||||
ZEND_ARG_INFO(0, unit)
|
||||
ZEND_ARG_INFO(0, options)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_geosearchstore, 0, 0, 5)
|
||||
ZEND_ARG_INFO(0, dst)
|
||||
ZEND_ARG_INFO(0, src)
|
||||
ZEND_ARG_INFO(0, position)
|
||||
ZEND_ARG_INFO(0, shape)
|
||||
ZEND_ARG_INFO(0, unit)
|
||||
ZEND_ARG_INFO(0, options)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_Redis_get arginfo_class_Redis__prefix
|
||||
|
||||
#define arginfo_class_Redis_getAuth arginfo_class_Redis___destruct
|
||||
@@ -876,6 +893,8 @@ ZEND_METHOD(Redis, georadius);
|
||||
ZEND_METHOD(Redis, georadius_ro);
|
||||
ZEND_METHOD(Redis, georadiusbymember);
|
||||
ZEND_METHOD(Redis, georadiusbymember_ro);
|
||||
ZEND_METHOD(Redis, geosearch);
|
||||
ZEND_METHOD(Redis, geosearchstore);
|
||||
ZEND_METHOD(Redis, get);
|
||||
ZEND_METHOD(Redis, getAuth);
|
||||
ZEND_METHOD(Redis, getBit);
|
||||
@@ -1099,6 +1118,8 @@ static const zend_function_entry class_Redis_methods[] = {
|
||||
ZEND_ME(Redis, georadius_ro, arginfo_class_Redis_georadius_ro, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, georadiusbymember, arginfo_class_Redis_georadiusbymember, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, georadiusbymember_ro, arginfo_class_Redis_georadiusbymember_ro, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, geosearch, arginfo_class_Redis_geosearch, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, geosearchstore, arginfo_class_Redis_geosearchstore, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, get, arginfo_class_Redis_get, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, getAuth, arginfo_class_Redis_getAuth, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, getBit, arginfo_class_Redis_getBit, ZEND_ACC_PUBLIC)
|
||||
|
||||
@@ -58,6 +58,8 @@ class Redis_Cluster_Test extends Redis_Test {
|
||||
public function testzMscore() { return $this->marktestSkipped(); }
|
||||
public function testZRandMember() { return $this->marktestSkipped(); }
|
||||
public function testCopy() { return $this->marktestSkipped(); }
|
||||
public function testGeoSearch() { return $this->marktestSkipped(); }
|
||||
public function testGeoSearchStore() { return $this->marktestSkipped(); }
|
||||
|
||||
/* Session locking feature is currently not supported in in context of Redis Cluster.
|
||||
The biggest issue for this is the distribution nature of Redis cluster */
|
||||
|
||||
@@ -5875,6 +5875,34 @@ class Redis_Test extends TestSuite
|
||||
$this->assertEquals(round($r1, 8), round($r2, 8));
|
||||
}
|
||||
|
||||
public function testGeoSearch() {
|
||||
if (!$this->minVersionCheck("6.2.0")) {
|
||||
return $this->markTestSkipped();
|
||||
}
|
||||
|
||||
$this->addCities('gk');
|
||||
|
||||
$this->assertEquals($this->redis->geosearch('gk', 'Chico', 1, 'm'), ['Chico']);
|
||||
$this->assertValidate($this->redis->geosearch('gk', 'Chico', 1, 'm', ['withcoord', 'withdist', 'withhash']), function ($v) {
|
||||
$this->assertArrayKey($v, 'Chico', 'is_array');
|
||||
$this->assertEquals(count($v['Chico']), 3);
|
||||
$this->assertArrayKey($v['Chico'], 0, 'is_float');
|
||||
$this->assertArrayKey($v['Chico'], 1, 'is_int');
|
||||
$this->assertArrayKey($v['Chico'], 2, 'is_array');
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public function testGeoSearchStore() {
|
||||
if (!$this->minVersionCheck("6.2.0")) {
|
||||
return $this->markTestSkipped();
|
||||
}
|
||||
|
||||
$this->addCities('gk');
|
||||
$this->assertEquals($this->redis->geosearchstore('{gk}', 'gk', 'Chico', 100, 'km'), 3);
|
||||
$this->assertEquals($this->redis->geosearch('{gk}', 'Chico', 1, 'm'), ['Chico']);
|
||||
}
|
||||
|
||||
/* Test a 'raw' command */
|
||||
public function testRawCommand() {
|
||||
$this->redis->set('mykey','some-value');
|
||||
|
||||
Reference in New Issue
Block a user