Skip to content

Commit 8dbbf8c

Browse files
feat: add support for distance operator <@> (#361)
Co-authored-by: Martin Georgiev <martin-georgiev@users.noreply.github.com>
1 parent 88635d7 commit 8dbbf8c

File tree

6 files changed

+80
-0
lines changed

6 files changed

+80
-0
lines changed

docs/INTEGRATING-WITH-DOCTRINE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ $configuration->addCustomStringFunction('REGEXP_MATCH', MartinGeorgiev\Doctrine\
163163
$configuration->addCustomStringFunction('STRCONCAT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StrConcat::class);
164164
$configuration->addCustomStringFunction('REGEXP_REPLACE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpReplace::class);
165165
$configuration->addCustomStringFunction('ROW', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Row::class);
166+
$configuration->addCustomStringFunction('DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Distance::class);
166167

167168
# aggregation functions
168169
$configuration->addCustomStringFunction('ARRAY_AGG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayAgg::class);

docs/INTEGRATING-WITH-LARAVEL.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ return [
218218
'REGEXP_SUBSTR' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpSubstr::class,
219219
'STRCONCAT' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StrConcat::class, // the `||` operator
220220
'ROW' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Row::class,
221+
'DISTANCE' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Distance::class,
221222

222223
# aggregation functions
223224
'ARRAY_AGG' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayAgg::class,

docs/INTEGRATING-WITH-SYMFONY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ doctrine:
212212
REGEXP_SUBSTR: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpSubstr
213213
ROW: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Row
214214
STRCONCAT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StrConcat
215+
DISTANCE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Distance
215216
216217
# aggregation functions
217218
ARRAY_AGG: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayAgg
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Fixtures\MartinGeorgiev\Doctrine\Entity;
6+
7+
use Doctrine\ORM\Mapping as ORM;
8+
use MartinGeorgiev\Doctrine\DBAL\Types\ValueObject\Point;
9+
10+
#[ORM\Entity()]
11+
class ContainsPoints extends Entity
12+
{
13+
#[ORM\Column(type: 'point')]
14+
public Point $point1;
15+
16+
#[ORM\Column(type: 'point')]
17+
public Point $point2;
18+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
/**
8+
* Implementation of PostgreSQL's distance operator (using `<@>`).
9+
*
10+
* @see https://www.postgresql.org/docs/17/earthdistance.html#EARTHDISTANCE-POINT-BASED
11+
* @since 3.1
12+
*
13+
* @author Sébastien Jean <sebastien.jean76@gmail.com>
14+
*/
15+
class Distance extends BaseFunction
16+
{
17+
protected function customizeFunction(): void
18+
{
19+
$this->setFunctionPrototype('(%s <@> %s)');
20+
$this->addNodeMapping('StringPrimary');
21+
$this->addNodeMapping('StringPrimary');
22+
}
23+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsPoints;
8+
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Distance;
9+
10+
class DistanceTest extends TestCase
11+
{
12+
protected function getStringFunctions(): array
13+
{
14+
return [
15+
'DISTANCE' => Distance::class,
16+
];
17+
}
18+
19+
protected function getExpectedSqlStatements(): array
20+
{
21+
return [
22+
"SELECT (c0_.point1 <@> '(2.320041, 48.858889)') AS sclr_0 FROM ContainsPoints c0_",
23+
'SELECT (c0_.point1 <@> c0_.point2) AS sclr_0 FROM ContainsPoints c0_',
24+
"SELECT ('(1.0, 1.0)' <@> '(2.0, 2.0)') AS sclr_0 FROM ContainsPoints c0_",
25+
];
26+
}
27+
28+
protected function getDqlStatements(): array
29+
{
30+
return [
31+
\sprintf("SELECT DISTANCE(e.point1, '(2.320041, 48.858889)') FROM %s e", ContainsPoints::class),
32+
\sprintf('SELECT DISTANCE(e.point1, e.point2) FROM %s e', ContainsPoints::class),
33+
\sprintf("SELECT DISTANCE('(1.0, 1.0)', '(2.0, 2.0)') FROM %s e", ContainsPoints::class),
34+
];
35+
}
36+
}

0 commit comments

Comments
 (0)