Skip to content
Merged
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,16 @@ This package provides comprehensive Doctrine support for PostgreSQL features:
- **Range Operations**
- Containment checks (in PHP value objects and for DQL queries with `@>` and `<@`)
- Overlaps (`&&`)
- **PostGIS Spatial Operations**
- Bounding box relationships (`<<`, `>>`, `&<`, `&>`, `|&>`, `&<|`, `<<|`, `|>>`)
- Spatial containment (`@`, `~`)
- Distance calculations (`<->`, `<#>`, `<<->>`, `<<#>>`, `|=|`)
- N-dimensional operations (`&&&`)

### Functions
- **Text Search**
- Full text search (`to_tsvector`, `to_tsquery`)
- Pattern matching (`ILIKE`, `SIMILAR TO`)
- Pattern matching (`ilike`, `similar to`)
- Regular expressions
- **Array Functions**
- Array aggregation (`array_agg`)
Expand Down
103 changes: 97 additions & 6 deletions docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
# Available operators
# Available Operators

| PostgreSQL operator | Register for DQL as | Implemented by
## Operator Conflicts and Usage Notes

**⚠️ Important**: Some PostgreSQL operators have multiple meanings depending on the data types involved. This library provides specific DQL function names to avoid conflicts:

| Operator | Array/JSON Usage | Spatial Usage | Text/Pattern Usage |
|---|---|---|---|
| `@>` | `CONTAINS` (arrays contain elements) | Works automatically with geometry/geography | N/A |
| `<@` | `IS_CONTAINED_BY` (element in array) | Works automatically with geometry/geography | N/A |
| `@` | N/A | `SPATIAL_CONTAINED_BY` (bounding box contained) | N/A |
| `~` | N/A | `SPATIAL_CONTAINS` (bounding box contains) | `REGEXP` (text pattern matching) |
| `&&` | `OVERLAPS` (arrays/ranges overlap) | Works automatically with geometry/geography | N/A |
Comment on lines +9 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct spatial-usage cells for @> and <@ (they don’t apply to PostGIS bbox semantics).

Listing them as “Works automatically with geometry/geography” is misleading; PostGIS uses @ and ~ for bbox contain/contained-by. Keep these N/A under Spatial.

-| `@>` | `CONTAINS` (arrays contain elements) | Works automatically with geometry/geography | N/A |
-| `<@` | `IS_CONTAINED_BY` (element in array) | Works automatically with geometry/geography | N/A |
+| `@>` | `CONTAINS` (arrays contain elements) | N/A | N/A |
+| `<@` | `IS_CONTAINED_BY` (element in array) | N/A | N/A |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| `@>` | `CONTAINS` (arrays contain elements) | Works automatically with geometry/geography | N/A |
| `<@` | `IS_CONTAINED_BY` (element in array) | Works automatically with geometry/geography | N/A |
| `@` | N/A | `SPATIAL_CONTAINED_BY` (bounding box contained) | N/A |
| `~` | N/A | `SPATIAL_CONTAINS` (bounding box contains) | `REGEXP` (text pattern matching) |
| `&&` | `OVERLAPS` (arrays/ranges overlap) | Works automatically with geometry/geography | N/A |
| `@>` | `CONTAINS` (arrays contain elements) | N/A | N/A |
| `<@` | `IS_CONTAINED_BY` (element in array) | N/A | N/A |
| `@` | N/A | `SPATIAL_CONTAINED_BY` (bounding box contained) | N/A |
| `~` | N/A | `SPATIAL_CONTAINS` (bounding box contains) | `REGEXP` (text pattern matching) |
| `&&` | `OVERLAPS` (arrays/ranges overlap) | Works automatically with geometry/geography | N/A |
🧰 Tools
🪛 LanguageTool

[grammar] ~9-~9: There might be a mistake here.
Context: ...atically with geometry/geography | N/A | | <@ | IS_CONTAINED_BY (element in a...

(QB_NEW_EN)


[grammar] ~10-~10: There might be a mistake here.
Context: ...atically with geometry/geography | N/A | | @ | N/A | SPATIAL_CONTAINED_BY (bo...

(QB_NEW_EN)


[grammar] ~11-11: There might be a mistake here.
Context: ...NED_BY(bounding box contained) | N/A | |
| N/A |SPATIAL_CONTAINS` (boundi...

(QB_NEW_EN)


[grammar] ~12-~12: There might be a mistake here.
Context: ...ns) | REGEXP (text pattern matching) | | && | OVERLAPS (arrays/ranges overl...

(QB_NEW_EN)

🤖 Prompt for AI Agents
In docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md around lines 9-13, the
spatial-usage cells for the `@>` and `<@` rows are incorrect; change their
Spatial column entries from "Works automatically with geometry/geography" to
"N/A" (since PostGIS bbox semantics use `@` and `~`), verify that the `@` row is
labeled `SPATIAL_CONTAINED_BY` and the `~` row is labeled `SPATIAL_CONTAINS`,
and ensure the table consistently marks only `@` and `~` as the spatial bbox
operators while keeping `@>` and `<@` as array operators only.


**Usage Guidelines:**
- **Arrays/JSON**: Use `CONTAINS`, `IS_CONTAINED_BY`, `OVERLAPS` for array and JSON operations
- **Spatial**: Use `SPATIAL_CONTAINS`, `SPATIAL_CONTAINED_BY` for explicit spatial bounding box operations
- **Text**: Use `REGEXP`, `IREGEXP` for pattern matching
- **Boolean operators**: All spatial operators return boolean values and **shall be used with `= TRUE` or `= FALSE` in DQL**

## General Operators

| PostgreSQL operator | Register for DQL as | Implemented by |
|---|---|---|
| @> | CONTAINS | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Contains` |
| <@ | IS_CONTAINED_BY | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\IsContainedBy` |
Expand All @@ -24,9 +44,80 @@
| @@ | TSMATCH | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tsmatch` |
| \|\| | STRCONCAT | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StrConcat` |

# Available functions
## PostGIS Spatial Operators

**⚠️ Important**: Some operators have dual meanings for different data types. Use the specific DQL function names to avoid conflicts:

- **`@`**: Use `CONTAINS` for arrays/JSON, `SPATIAL_CONTAINED_BY` for geometry/geography
- **`~`**: Use `REGEXP` for text patterns, `SPATIAL_CONTAINS` for geometry/geography
- **`&&`**: Use `OVERLAPS` for arrays/JSON, spatial overlaps work automatically with geometry/geography

**📝 Compatibility Notes**:
- Most bounding box operators work primarily with **geometry** types
- **Geography** types have limited operator support (mainly `&&`, `<->`, `<@>`)
- **3D/n-dimensional operators** may require explicit type casting: `ST_GeomFromText('POINT Z(0 0 0)')`
Comment on lines +55 to +58
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

❓ Verification inconclusive

Tighten compatibility notes for geography and remove likely-incorrect <@> reference.

Geography reliably supports && and KNN <-> in recent PostGIS; <@> is not a PostGIS geography operator.

-- **Geography** types have limited operator support (mainly `&&`, `<->`, `<@>`)
+- **Geography** types have limited operator support (commonly `&&`, `<->` with KNN GiST/SP-GiST)

Update geography compatibility notes
Based on the PostGIS documentation, geography columns support only the standard bounding-box intersection operator and KNN distance operator, not the <@> containment operator:

  • The && operator is defined for both geometry and geography types (stackoverflow.com)
  • The <-> operator provides KNN (“K nearest neighbour”) distance ordering for geography as well as geometry (postgis.net)
  • The @ (and any variant like <@>) operator is only defined on geometry types; geography does not support it (access.crunchydata.com, stackoverflow.com)

Please apply this change to docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md (around lines 55–58):

- **Geography** types have limited operator support (mainly `&&`, `<->`, `<@>`)
+ **Geography** types have limited operator support (commonly `&&`, `<->` with KNN GiST/SP-GiST)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**📝 Compatibility Notes**:
- Most bounding box operators work primarily with **geometry** types
- **Geography** types have limited operator support (mainly `&&`, `<->`, `<@>`)
- **3D/n-dimensional operators** may require explicit type casting: `ST_GeomFromText('POINT Z(0 0 0)')`
**📝 Compatibility Notes**:
- Most bounding box operators work primarily with **geometry** types
- **Geography** types have limited operator support (commonly `&&`, `<->` with KNN GiST/SP-GiST)
- **3D/n-dimensional operators** may require explicit type casting: `ST_GeomFromText('POINT Z(0 0 0)')`
🧰 Tools
🪛 LanguageTool

[grammar] ~55-~55: There might be a mistake here.
Context: ...y/geography 📝 Compatibility Notes: - Most bounding box operators work primari...

(QB_NEW_EN)


[grammar] ~56-~56: There might be a mistake here.
Context: ...s work primarily with geometry types - Geography types have limited operator ...

(QB_NEW_EN)


[grammar] ~57-~57: There might be a mistake here.
Context: ...ator support (mainly &&, <->, <@>) - 3D/n-dimensional operators may require...

(QB_NEW_EN)

🤖 Prompt for AI Agents
In docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md around lines 55 to 58, update the
geography compatibility notes to reflect PostGIS docs: state that geography
supports the bounding-box intersection operator (`&&`) and the KNN distance
operator (`<->` but not the containment operator variant like `<@>` or `@`), and
remove or replace the incorrect claim that `<@>` is supported for geography;
edit the three bullet points so they explicitly list `&&` and `<->` for
geography and note that containment operators (e.g., `<@>`, `@`) are
geometry-only.

- Some advanced operators (`&&&`, `<<#>>`) may not be available in all PostGIS versions

### Bounding Box Operators

These operators work with geometry and geography bounding boxes. All return boolean values and **shall be used with `= TRUE` or `= FALSE` in DQL**.

| PostgreSQL operator | Register for DQL as | Description | Implemented by |
|---|---|---|---|
| &< | OVERLAPS_LEFT | Returns TRUE if A's bounding box overlaps or is to the left of B's | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\OverlapsLeft` |
| &> | OVERLAPS_RIGHT | Returns TRUE if A's bounding box overlaps or is to the right of B's | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\OverlapsRight` |
| << | STRICTLY_LEFT | Returns TRUE if A's bounding box is strictly to the left of B's | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StrictlyLeft` |
| >> | STRICTLY_RIGHT | Returns TRUE if A's bounding box is strictly to the right of B's | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StrictlyRight` |
| @ | SPATIAL_CONTAINED_BY | Returns TRUE if A's bounding box is contained by B's (**spatial version**) | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SpatialContainedBy` |
| ~ | SPATIAL_CONTAINS | Returns TRUE if A's bounding box contains B's (**spatial version**) | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SpatialContains` |
| ~= | SPATIAL_SAME | Returns TRUE if A's bounding box is the same as B's | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SpatialSame` |
| \|&> | OVERLAPS_ABOVE | Returns TRUE if A's bounding box overlaps or is above B's | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\OverlapsAbove` |
| \|>> | STRICTLY_ABOVE | Returns TRUE if A's bounding box is strictly above B's | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StrictlyAbove` |
| &<\| | OVERLAPS_BELOW | Returns TRUE if A's bounding box overlaps or is below B's | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\OverlapsBelow` |
| <<\| | STRICTLY_BELOW | Returns TRUE if A's bounding box is strictly below B's | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StrictlyBelow` |
| &&& | ND_OVERLAPS | Returns TRUE if A's n-D bounding box intersects B's n-D bounding box | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NDimensionalOverlaps` |

**Usage Examples:**
```sql
-- Find geometries to the left of a reference point
SELECT e FROM Entity e WHERE STRICTLY_LEFT(e.geometry, 'POINT(0 0)') = TRUE

-- Find overlapping polygons
SELECT e FROM Entity e WHERE SPATIAL_CONTAINS(e.polygon, e.point) = TRUE

-- 3D spatial relationships
SELECT e FROM Entity e WHERE ND_OVERLAPS(e.geometry3d, 'POLYGON Z((0 0 0, 1 1 1, 2 2 2, 0 0 0))') = TRUE
```

### Distance Operators

These operators calculate distances between geometries. All return numeric values.

| PostgreSQL operator | Register for DQL as | Description | Implemented by |
|---|---|---|---|
| <-> | GEOMETRY_DISTANCE | Returns the 2D distance between A and B geometries | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\GeometryDistance` |
| <@> | DISTANCE | Returns distance between points (legacy operator) | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Distance` |
| \|=\| | TRAJECTORY_DISTANCE | Returns distance between trajectories at closest point of approach | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TrajectoryDistance` |
| <#> | BOUNDING_BOX_DISTANCE | Returns the 2D distance between A and B bounding boxes | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BoundingBoxDistance` |
| <<->> | ND_CENTROID_DISTANCE | Returns n-D distance between centroids of bounding boxes | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NDimensionalCentroidDistance` |
| <<#>> | ND_BOUNDING_BOX_DISTANCE | Returns the n-D distance between A and B bounding boxes | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NDimensionalBoundingBoxDistance` |

**Usage Examples:**
```sql
-- Find nearest geometries
SELECT e, GEOMETRY_DISTANCE(e.geometry, 'POINT(0 0)') as distance
FROM Entity e ORDER BY distance LIMIT 10

-- Bounding box distance for index optimization
SELECT e FROM Entity e WHERE BOUNDING_BOX_DISTANCE(e.geometry, 'POINT(0 0)') < 1000

-- 3D distance calculations
SELECT ND_CENTROID_DISTANCE(e.geometry3d1, e.geometry3d2) as distance FROM Entity e
```

# Available Functions

| PostgreSQL functions | Register for DQL as | Implemented by
| PostgreSQL functions | Register for DQL as | Implemented by |
|---|---|---|
| all | ALL_OF | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\All` |
| any | ANY_OF | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Any` |
Expand Down Expand Up @@ -134,9 +225,9 @@
| width_bucket | WIDTH_BUCKET | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\WidthBucket` |


# Bonus helpers
# Bonus Helpers

| PostgreSQL functions | Register for DQL as | Implemented by
| PostgreSQL functions | Register for DQL as | Implemented by |
|---|---|---|
| array | ARRAY | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Arr` |
| value = ANY(list of values) | IN_ARRAY | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\InArray` |
Expand Down
80 changes: 79 additions & 1 deletion docs/USE-CASES-AND-EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,87 @@ POLYGONZM((...)) => POLYGON ZM((...))
POINT Z (1 2 3) => POINT Z(1 2 3)
```

### Using PostGIS Spatial Operators in DQL

PostGIS spatial operators allow you to perform spatial queries using bounding box relationships and distance calculations. **Important**: All spatial operators return boolean values and shall be used with `= TRUE` or `= FALSE` in DQL.

#### Bounding Box Spatial Relationships

```sql
-- Find geometries to the left of a reference point
SELECT e FROM Entity e WHERE STRICTLY_LEFT(e.geometry, 'POINT(0 0)') = TRUE

-- Find geometries that spatially contain a point (bounding box level)
SELECT e FROM Entity e WHERE SPATIAL_CONTAINS(e.polygon, 'POINT(1 1)') = TRUE

-- Find geometries contained within a bounding box
SELECT e FROM Entity e WHERE SPATIAL_CONTAINED_BY(e.geometry, 'POLYGON((0 0, 10 10, 20 20, 0 0))') = TRUE

-- Check if two geometries have the same bounding box
SELECT e FROM Entity e WHERE SPATIAL_SAME(e.geometry1, e.geometry2) = TRUE

-- Vertical relationships
SELECT e FROM Entity e WHERE STRICTLY_ABOVE(e.geometry, 'LINESTRING(0 0, 5 0)') = TRUE
SELECT e FROM Entity e WHERE OVERLAPS_BELOW(e.geometry, 'POLYGON((0 5, 5 5, 5 10, 0 10, 0 5))') = TRUE

-- 3D spatial relationships
SELECT e FROM Entity e WHERE ND_OVERLAPS(e.geometry3d, 'POLYGON Z((0 0 0, 1 1 1, 2 2 2, 0 0 0))') = TRUE
```
Comment on lines +183 to +206
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix invalid/degenerate WKT in examples.

POLYGON((0 0, 10 10, 20 20, 0 0)) is colinear and invalid. Provide valid rings; also prefer simple rectangles for clarity. The 3D polygon example is likewise degenerate.

-SELECT e FROM Entity e WHERE SPATIAL_CONTAINED_BY(e.geometry, 'POLYGON((0 0, 10 10, 20 20, 0 0))') = TRUE
+SELECT e FROM Entity e WHERE SPATIAL_CONTAINED_BY(e.geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))') = TRUE
@@
-SELECT e FROM Entity e WHERE ND_OVERLAPS(e.geometry3d, 'POLYGON Z((0 0 0, 1 1 1, 2 2 2, 0 0 0))') = TRUE
+SELECT e FROM Entity e WHERE ND_OVERLAPS(e.geometry3d, 'POLYGON Z((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0))') = TRUE
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
PostGIS spatial operators allow you to perform spatial queries using bounding box relationships and distance calculations. **Important**: All spatial operators return boolean values and shall be used with `= TRUE` or `= FALSE` in DQL.
#### Bounding Box Spatial Relationships
```sql
-- Find geometries to the left of a reference point
SELECT e FROM Entity e WHERE STRICTLY_LEFT(e.geometry, 'POINT(0 0)') = TRUE
-- Find geometries that spatially contain a point (bounding box level)
SELECT e FROM Entity e WHERE SPATIAL_CONTAINS(e.polygon, 'POINT(1 1)') = TRUE
-- Find geometries contained within a bounding box
SELECT e FROM Entity e WHERE SPATIAL_CONTAINED_BY(e.geometry, 'POLYGON((0 0, 10 10, 20 20, 0 0))') = TRUE
-- Check if two geometries have the same bounding box
SELECT e FROM Entity e WHERE SPATIAL_SAME(e.geometry1, e.geometry2) = TRUE
-- Vertical relationships
SELECT e FROM Entity e WHERE STRICTLY_ABOVE(e.geometry, 'LINESTRING(0 0, 5 0)') = TRUE
SELECT e FROM Entity e WHERE OVERLAPS_BELOW(e.geometry, 'POLYGON((0 5, 5 5, 5 10, 0 10, 0 5))') = TRUE
-- 3D spatial relationships
SELECT e FROM Entity e WHERE ND_OVERLAPS(e.geometry3d, 'POLYGON Z((0 0 0, 1 1 1, 2 2 2, 0 0 0))') = TRUE
```
#### Bounding Box Spatial Relationships


#### Distance-Based Queries

```sql
-- Find the 10 nearest geometries to a point
SELECT e, GEOMETRY_DISTANCE(e.geometry, 'POINT(0 0)') as distance
FROM Entity e
ORDER BY distance
LIMIT 10

-- Find geometries within a specific distance (using bounding box distance for performance)
SELECT e FROM Entity e WHERE BOUNDING_BOX_DISTANCE(e.geometry, 'POINT(0 0)') < 1000

-- Calculate trajectory distances (for linestrings with measure values)
SELECT TRAJECTORY_DISTANCE(e.trajectory1, e.trajectory2) as closest_approach
FROM Entity e
WHERE e.trajectory1 IS NOT NULL

-- 3D distance calculations
SELECT e, ND_CENTROID_DISTANCE(e.geometry3d1, e.geometry3d2) as distance3d
FROM Entity e
WHERE ND_BOUNDING_BOX_DISTANCE(e.geometry3d1, e.geometry3d2) < 500
```

#### Operator Conflicts and Best Practices

Some operators have different meanings for different data types. Use specific function names to avoid conflicts:

```sql
-- ✅ CORRECT: Use specific function names
SELECT e FROM Entity e WHERE CONTAINS(e.tags, ARRAY['tag1']) = TRUE -- Array containment
SELECT e FROM Entity e WHERE SPATIAL_CONTAINS(e.polygon, e.point) = TRUE -- Spatial containment
SELECT e FROM Entity e WHERE REGEXP(e.text, 'pattern') = TRUE -- Text pattern matching

-- ❌ AVOID: Ambiguous usage that might conflict
-- The @ and ~ operators have different meanings for arrays vs spatial data
```

#### Performance Tips

```sql
-- Use bounding box operators for initial filtering (they use spatial indexes)
SELECT e FROM Entity e
WHERE OVERLAPS(e.geometry, 'POLYGON((0 0, 10 10, 20 20, 0 0))') = TRUE
AND ST_Intersects(e.geometry, 'POLYGON((0 0, 10 10, 20 20, 0 0))') -- Exact check

-- Use distance operators for nearest neighbor queries
SELECT e FROM Entity e
ORDER BY GEOMETRY_DISTANCE(e.geometry, 'POINT(0 0)')
LIMIT 10
```

For multi-item arrays, see [GEOMETRY-ARRAYS.md](./GEOMETRY-ARRAYS.md) for Doctrine DQL limitations and the suggested workarounds.

The library provides DBAL type support for PostGIS `geometry` and `geography` columns. Example usage:
The library provides DBAL type support for PostGIS `geometry` and `geography` types. Example usage:

```sql
CREATE TABLE places (
Expand Down
24 changes: 24 additions & 0 deletions fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Fixtures\MartinGeorgiev\Doctrine\Entity;

use Doctrine\ORM\Mapping as ORM;
use MartinGeorgiev\Doctrine\DBAL\Types\ValueObject\WktSpatialData;

#[ORM\Entity()]
class ContainsGeometries extends Entity
{
#[ORM\Column(type: 'geometry')]
public WktSpatialData $geometry1;

#[ORM\Column(type: 'geometry')]
public WktSpatialData $geometry2;

#[ORM\Column(type: 'geography')]
public WktSpatialData $geography1;

#[ORM\Column(type: 'geography')]
public WktSpatialData $geography2;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

/**
* Implementation of PostGIS 2D bounding box distance operator (using <#>).
*
* Returns the 2D distance between A and B bounding boxes.
* This is useful for index-based distance queries.
*
* @see https://postgis.net/docs/reference.html#Operators_Distance
* @since 3.5
*
* @author Martin Georgiev <martin.georgiev@gmail.com>
*
* @example Using it in DQL: "SELECT BOUNDING_BOX_DISTANCE(g1.geometry, g2.geometry) FROM Entity g1, Entity g2"
* Returns numeric distance value.
*/
class BoundingBoxDistance extends BaseFunction
{
protected function customizeFunction(): void
{
$this->setFunctionPrototype('(%s <#> %s)');
$this->addNodeMapping('StringPrimary');
$this->addNodeMapping('StringPrimary');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

/**
* Implementation of PostGIS 2D distance between geometries operator (using <->).
*
* Returns the 2D distance between A and B geometries.
* This differs from BoundingBoxDistance (using <#>), which measures distance between
* bounding boxes only. The <-> operator is commonly used for KNN nearest-neighbor
* ordering, and on PostgreSQL 9.5+ with PostGIS 2.2+ it returns true geometry distance;
* on older stacks it behaved as a centroid-of-bounding-box distance approximation.
*
* @see https://postgis.net/docs/reference.html#Operators
* @see https://postgis.net/docs/geometry_distance_knn.html
* @since 3.5
*
* @author Martin Georgiev <martin.georgiev@gmail.com>
*
* @example Using it in DQL: "SELECT GEOMETRY_DISTANCE(g1.geometry, g2.geometry) FROM Entity g1, Entity g2"
* Returns numeric distance value.
*/
class GeometryDistance extends BaseFunction
{
protected function customizeFunction(): void
{
$this->setFunctionPrototype('(%s <-> %s)');
$this->addNodeMapping('StringPrimary');
$this->addNodeMapping('StringPrimary');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

/**
* Implementation of PostGIS n-D bounding box distance operator (using <<#>>).
*
* Returns the n-D distance between A and B bounding boxes.
* This operator works with multi-dimensional geometries.
*
* @see https://postgis.net/docs/reference.html#Operators_Distance
* @since 3.5
*
* @author Martin Georgiev <martin.georgiev@gmail.com>
*
* @example Using it in DQL: "SELECT ND_BOUNDING_BOX_DISTANCE(g1.geometry, g2.geometry) FROM Entity g1, Entity g2"
* Returns numeric distance value.
*/
class NDimensionalBoundingBoxDistance extends BaseFunction
{
protected function customizeFunction(): void
{
$this->setFunctionPrototype('(%s <<#>> %s)');
$this->addNodeMapping('StringPrimary');
$this->addNodeMapping('StringPrimary');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

/**
* Implementation of PostGIS n-D centroid distance operator (using <<->>).
*
* Returns the n-D distance between the centroids of A and B bounding boxes.
* This operator works with multi-dimensional geometries.
*
* @see https://postgis.net/docs/reference.html#Operators_Distance
* @since 3.5
*
* @author Martin Georgiev <martin.georgiev@gmail.com>
*
* @example Using it in DQL: "SELECT ND_CENTROID_DISTANCE(g1.geometry, g2.geometry) FROM Entity g1, Entity g2"
* Returns numeric distance value.
*/
class NDimensionalCentroidDistance extends BaseFunction
{
protected function customizeFunction(): void
{
$this->setFunctionPrototype('(%s <<->> %s)');
$this->addNodeMapping('StringPrimary');
$this->addNodeMapping('StringPrimary');
}
}
Loading
Loading