Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8d369f4

Browse files
ImplementGEOSEARCH[STORE]BYPOLYGON.
Valkey 9.0.0 implemented a new variant of `GEOSEARCH` where you supplythe verticies to an arbitrary polygon.Since we can't modify the `geosearch` prototype using it is a littlewonky (you need to just pass empty strings for position and unit).```php$redis->geosearch('ca:cities', '', [ -121.90, 39.65, -121.77, 39.65, -121.77, 39.80, -121.90, 39.80], '');$redis->geosearchstore('ca:cities', 'dst', '', [ -121.90, 39.65, -121.77, 39.65, -121.77, 39.80, -121.90, 39.80], '');```
1 parentb1b0c19 commit8d369f4

File tree

4 files changed

+138
-49
lines changed

4 files changed

+138
-49
lines changed

‎redis_commands.c‎

Lines changed: 106 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4475,38 +4475,56 @@ redis_geosearch_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
44754475
char**cmd,int*cmd_len,short*slot,void**ctx)
44764476
{
44774477
char*key,*unit;
4478-
intargc=2;
4478+
intargc=0;
44794479
size_tkeylen,unitlen;
44804480
geoOptionsgopts= {0};
44814481
smart_stringcmdstr= {0};
44824482
zval*position,*shape,*opts=NULL,*z_ele;
44834483
zend_string*zkey,*zstr;
4484+
zend_boolbypolygon=0;
4485+
HashTable*ht;
44844486

4485-
if (zend_parse_parameters(ZEND_NUM_ARGS(),"szzs|a",
4486-
&key,&keylen,&position,&shape,
4487-
&unit,&unitlen,&opts)==FAILURE)
4487+
if (zend_parse_parameters(ZEND_NUM_ARGS(),"szzs|a",&key,&keylen,
4488+
&position,&shape,&unit,&unitlen,
4489+
&opts)==FAILURE)
44884490
{
44894491
returnFAILURE;
44904492
}
44914493

4492-
if (Z_TYPE_P(position)==IS_STRING&&Z_STRLEN_P(position)>0) {
4493-
argc+=2;
4494-
}elseif (Z_TYPE_P(position)==IS_ARRAY&&zend_hash_num_elements(Z_ARRVAL_P(position))==2) {
4495-
argc+=3;
4496-
}else {
4497-
php_error_docref(NULL,E_WARNING,"Invalid position");
4498-
returnFAILURE;
4499-
}
4500-
45014494
if (Z_TYPE_P(shape)==IS_LONG||Z_TYPE_P(shape)==IS_DOUBLE) {
45024495
argc+=2;
4503-
}elseif (Z_TYPE_P(shape)==IS_ARRAY) {
4496+
}elseif (Z_TYPE_P(shape)==IS_ARRAY&&
4497+
zend_hash_num_elements(Z_ARRVAL_P(shape))==2)
4498+
{
4499+
// BYBOX
45044500
argc+=3;
4501+
}elseif (Z_TYPE_P(shape)==IS_ARRAY&&
4502+
zend_hash_num_elements(Z_ARRVAL_P(shape)) >=6&&
4503+
zend_hash_num_elements(Z_ARRVAL_P(shape)) %2==0)
4504+
{
4505+
// BYPOLYGON N verticies
4506+
argc+=2+zend_hash_num_elements(Z_ARRVAL_P(shape));
4507+
bypolygon=1;
45054508
}else {
45064509
php_error_docref(NULL,E_WARNING,"Invalid shape dimensions");
45074510
returnFAILURE;
45084511
}
45094512

4513+
if (!bypolygon) {
4514+
if (Z_TYPE_P(position)==IS_STRING&&Z_STRLEN_P(position)>0) {
4515+
argc+=2;
4516+
}elseif (Z_TYPE_P(position)==IS_ARRAY&&
4517+
zend_hash_num_elements(Z_ARRVAL_P(position))==2)
4518+
{
4519+
argc+=3;
4520+
}else {
4521+
php_error_docref(NULL,E_WARNING,"Invalid position");
4522+
returnFAILURE;
4523+
}
4524+
}
4525+
4526+
argc+=bypolygon ?1 :2;
4527+
45104528
/* Attempt to parse our options array */
45114529
if (opts!=NULL) {
45124530
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(opts),zkey,z_ele) {
@@ -4539,28 +4557,40 @@ redis_geosearch_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
45394557
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr,argc,"GEOSEARCH");
45404558
redis_cmd_append_sstr_key(&cmdstr,key,keylen,redis_sock,slot);
45414559

4542-
if (Z_TYPE_P(position)==IS_ARRAY) {
4543-
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"FROMLONLAT");
4544-
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(position),z_ele) {
4545-
ZVAL_DEREF(z_ele);
4546-
redis_cmd_append_sstr_dbl(&cmdstr,zval_get_double(z_ele));
4547-
}ZEND_HASH_FOREACH_END();
4548-
}else {
4549-
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"FROMMEMBER");
4550-
redis_cmd_append_sstr(&cmdstr,Z_STRVAL_P(position),Z_STRLEN_P(position));
4560+
if (!bypolygon) {
4561+
if (Z_TYPE_P(position)==IS_ARRAY) {
4562+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"FROMLONLAT");
4563+
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(position),z_ele) {
4564+
ZVAL_DEREF(z_ele);
4565+
redis_cmd_append_sstr_dbl(&cmdstr,zval_get_double(z_ele));
4566+
}ZEND_HASH_FOREACH_END();
4567+
}else {
4568+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"FROMMEMBER");
4569+
redis_cmd_append_sstr(&cmdstr,Z_STRVAL_P(position),Z_STRLEN_P(position));
4570+
}
45514571
}
45524572

45534573
if (Z_TYPE_P(shape)==IS_ARRAY) {
4554-
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"BYBOX");
4555-
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(shape),z_ele) {
4574+
ht=Z_ARRVAL_P(shape);
4575+
if (bypolygon) {
4576+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"BYPOLYGON");
4577+
redis_cmd_append_sstr_long(&cmdstr,zend_hash_num_elements(ht) /2);
4578+
}else {
4579+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"BYBOX");
4580+
}
4581+
4582+
ZEND_HASH_FOREACH_VAL(ht,z_ele) {
45564583
ZVAL_DEREF(z_ele);
45574584
redis_cmd_append_sstr_dbl(&cmdstr,zval_get_double(z_ele));
45584585
}ZEND_HASH_FOREACH_END();
45594586
}else {
45604587
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"BYRADIUS");
45614588
redis_cmd_append_sstr_dbl(&cmdstr,zval_get_double(shape));
45624589
}
4563-
redis_cmd_append_sstr(&cmdstr,unit,unitlen);
4590+
4591+
if (!bypolygon) {
4592+
redis_cmd_append_sstr(&cmdstr,unit,unitlen);
4593+
}
45644594

45654595
/* Append optional arguments */
45664596
if (gopts.withcoord)REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"WITHCOORD");
@@ -4597,14 +4627,16 @@ int
45974627
redis_geosearchstore_cmd(INTERNAL_FUNCTION_PARAMETERS,RedisSock*redis_sock,
45984628
char**cmd,int*cmd_len,short*slot,void**ctx)
45994629
{
4600-
intargc=3;
46014630
char*dest,*src,*unit;
46024631
size_tdestlen,srclen,unitlen;
46034632
geoOptionsgopts= {0};
46044633
smart_stringcmdstr= {0};
46054634
zval*position,*shape,*opts=NULL,*z_ele;
4635+
zend_boolbypolygon=0;
46064636
zend_string*zkey;
4637+
HashTable*ht;
46074638
shorts2=0;
4639+
intargc=0;
46084640

46094641
if (zend_parse_parameters(ZEND_NUM_ARGS(),"sszzs|a",
46104642
&dest,&destlen,&src,&srclen,&position,&shape,
@@ -4613,24 +4645,38 @@ redis_geosearchstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
46134645
returnFAILURE;
46144646
}
46154647

4616-
if (Z_TYPE_P(position)==IS_STRING&&Z_STRLEN_P(position)>0) {
4617-
argc+=2;
4618-
}elseif (Z_TYPE_P(position)==IS_ARRAY&&zend_hash_num_elements(Z_ARRVAL_P(position))==2) {
4619-
argc+=3;
4620-
}else {
4621-
php_error_docref(NULL,E_WARNING,"Invalid position");
4622-
returnFAILURE;
4623-
}
4624-
46254648
if (Z_TYPE_P(shape)==IS_LONG||Z_TYPE_P(shape)==IS_DOUBLE) {
46264649
argc+=2;
4627-
}elseif (Z_TYPE_P(shape)==IS_ARRAY) {
4650+
}elseif (Z_TYPE_P(shape)==IS_ARRAY&&
4651+
zend_hash_num_elements(Z_ARRVAL_P(shape))==2)
4652+
{
46284653
argc+=3;
4654+
}elseif (Z_TYPE_P(shape)==IS_ARRAY&&
4655+
zend_hash_num_elements(Z_ARRVAL_P(shape)) >=6&&
4656+
zend_hash_num_elements(Z_ARRVAL_P(shape)) %2==0)
4657+
{
4658+
argc+=2+zend_hash_num_elements(Z_ARRVAL_P(shape));
4659+
bypolygon=1;
46294660
}else {
46304661
php_error_docref(NULL,E_WARNING,"Invalid shape dimensions");
46314662
returnFAILURE;
46324663
}
46334664

4665+
argc+=bypolygon ?2 :3;
4666+
4667+
if (!bypolygon) {
4668+
if (Z_TYPE_P(position)==IS_STRING&&Z_STRLEN_P(position)>0) {
4669+
argc+=2;
4670+
}elseif (Z_TYPE_P(position)==IS_ARRAY&&
4671+
zend_hash_num_elements(Z_ARRVAL_P(position))==2)
4672+
{
4673+
argc+=3;
4674+
}else {
4675+
php_error_docref(NULL,E_WARNING,"Invalid position");
4676+
returnFAILURE;
4677+
}
4678+
}
4679+
46344680
/* Attempt to parse our options array */
46354681
if (opts!=NULL) {
46364682
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(opts),zkey,z_ele) {
@@ -4671,28 +4717,39 @@ redis_geosearchstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
46714717
returnFAILURE;
46724718
}
46734719

4674-
if (Z_TYPE_P(position)==IS_ARRAY) {
4675-
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"FROMLONLAT");
4676-
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(position),z_ele) {
4677-
ZVAL_DEREF(z_ele);
4678-
redis_cmd_append_sstr_dbl(&cmdstr,zval_get_double(z_ele));
4679-
}ZEND_HASH_FOREACH_END();
4680-
}else {
4681-
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"FROMMEMBER");
4682-
redis_cmd_append_sstr(&cmdstr,Z_STRVAL_P(position),Z_STRLEN_P(position));
4720+
if (!bypolygon) {
4721+
if (Z_TYPE_P(position)==IS_ARRAY) {
4722+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"FROMLONLAT");
4723+
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(position),z_ele) {
4724+
ZVAL_DEREF(z_ele);
4725+
redis_cmd_append_sstr_dbl(&cmdstr,zval_get_double(z_ele));
4726+
}ZEND_HASH_FOREACH_END();
4727+
}else {
4728+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"FROMMEMBER");
4729+
redis_cmd_append_sstr(&cmdstr,Z_STRVAL_P(position),Z_STRLEN_P(position));
4730+
}
46834731
}
46844732

46854733
if (Z_TYPE_P(shape)==IS_ARRAY) {
4686-
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"BYBOX");
4687-
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(shape),z_ele) {
4734+
ht=Z_ARRVAL_P(shape);
4735+
if (bypolygon) {
4736+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"BYPOLYGON");
4737+
redis_cmd_append_sstr_long(&cmdstr,zend_hash_num_elements(ht) /2);
4738+
}else {
4739+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"BYBOX");
4740+
}
4741+
ZEND_HASH_FOREACH_VAL(ht,z_ele) {
46884742
ZVAL_DEREF(z_ele);
46894743
redis_cmd_append_sstr_dbl(&cmdstr,zval_get_double(z_ele));
46904744
}ZEND_HASH_FOREACH_END();
46914745
}else {
46924746
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr,"BYRADIUS");
46934747
redis_cmd_append_sstr_dbl(&cmdstr,zval_get_double(shape));
46944748
}
4695-
redis_cmd_append_sstr(&cmdstr,unit,unitlen);
4749+
4750+
if (!bypolygon) {
4751+
redis_cmd_append_sstr(&cmdstr,unit,unitlen);
4752+
}
46964753

46974754
/* Append sort if it's not GEO_NONE */
46984755
if (gopts.sort==SORT_ASC) {

‎tests/RedisClusterTest.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ public function setUp() {
137137
$this->version =$info['redis_version'] ??'0.0.0';
138138
$this->is_keydb =$this->detectKeyDB($info);
139139
$this->is_valkey =$this->detectValkey($info);
140+
$this->valkey_version =$info['valkey_version'] ??'0.0.0';
140141
}
141142

142143
privatefunctionfindCliExe() {

‎tests/RedisTest.php‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public function setUp() {
7777
$this->version = (isset($info['redis_version'])?$info['redis_version']:'0.0.0');
7878
$this->is_keydb =$this->detectKeyDB($info);
7979
$this->is_valkey =$this->detectValKey($info);
80+
$this->valkey_version =$info['valkey_version'] ??'0.0.0';
8081
}
8182

8283
protectedfunctionhaveCommand(string$cmd):bool {
@@ -90,6 +91,10 @@ protected function minVersionCheck($version) {
9091
returnversion_compare($this->version,$version) >=0;
9192
}
9293

94+
protectedfunctionminValkeyVersionCheck($version) {
95+
return$this->is_valkey &&version_compare($this->valkey_version,$version) >=0;
96+
}
97+
9398
protectedfunctionmstime() {
9499
returnround(microtime(true)*1000);
95100
}
@@ -6913,6 +6918,31 @@ public function testGeoSearch() {
69136918
});
69146919
}
69156920

6921+
publicfunctiontestGeoSearchByPolygon() {
6922+
if ( !$this->minValkeyVersionCheck('9.0.0'))
6923+
$this->markTestSkipped();
6924+
6925+
$this->addCities('ca:cities');
6926+
6927+
$res =$this->redis->geosearch('ca:cities','', [
6928+
-121.90,39.65, -121.77,39.65, -121.77,39.80, -121.90,39.80
6929+
],'');
6930+
6931+
$this->assertEquals(['Chico'],$res);
6932+
}
6933+
6934+
publicfunctiontestGeoSearchStoreByPolygon() {
6935+
if ( !$this->minValkeyVersionCheck('9.0.0'))
6936+
$this->markTestSkipped();
6937+
6938+
$this->addCities('ca:cities');
6939+
$this->assertEquals(1,$this->redis->geosearchstore('{gk}dst','ca:cities','', [
6940+
-121.90,39.65, -121.77,39.65, -121.77,39.80, -121.90,39.80
6941+
],''));
6942+
6943+
$this->assertEquals(['Chico'],$this->redis->geosearch('{gk}dst','Chico',1,'m'));
6944+
}
6945+
69166946
publicfunctiontestGeoSearchStore() {
69176947
if ( !$this->minVersionCheck('6.2.0'))
69186948
$this->markTestSkipped();

‎tests/TestSuite.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class TestSuite
1515

1616
/* Redis server version */
1717
protected$version;
18+
protectedstring$valkey_version;
1819
protectedbool$is_keydb;
1920
protectedbool$is_valkey;
2021

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp