Skip to content

Conversation

@martin-georgiev
Copy link
Owner

@martin-georgiev martin-georgiev commented Sep 2, 2025

Summary by CodeRabbit

  • New Features

    • Many new PostGIS functions exposed in DQL for geometry operations: 2D/3D distances and lengths, area/perimeter, buffer/transform/translate/rotate/scale, envelope/centroid/convex hull, split/subdivide/collect/union/intersection/symmetric-difference, simplify variants, force 2D/3D/4D, projection and advanced distance metrics.
  • Tests

    • Comprehensive unit and integration tests added; fixtures now use SRID/EWKT, dataset expanded, and several integration assertions tightened for deterministic results.

@coveralls
Copy link

coveralls commented Sep 2, 2025

Coverage Status

coverage: 95.088% (+0.3%) from 94.768%
when pulling 2d01b14 on new-postgis-functions-2
into 1de5aaf on main.

@coderabbitai
Copy link

coderabbitai bot commented Sep 2, 2025

Warning

Rate limit exceeded

@martin-georgiev has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 2 minutes and 25 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between d35a98b and 2d01b14.

📒 Files selected for processing (18)
  • README.md (1 hunks)
  • docs/ARRAY-AND-JSON-FUNCTIONS.md (1 hunks)
  • docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md (2 hunks)
  • docs/DATE-AND-RANGE-FUNCTIONS.md (1 hunks)
  • docs/GEOMETRY-ARRAYS.md (1 hunks)
  • docs/INTEGRATING-WITH-DOCTRINE.md (1 hunks)
  • docs/INTEGRATING-WITH-LARAVEL.md (2 hunks)
  • docs/INTEGRATING-WITH-SYMFONY.md (1 hunks)
  • docs/MATHEMATICAL-FUNCTIONS.md (1 hunks)
  • docs/RANGE-TYPES.md (1 hunks)
  • docs/SPATIAL-FUNCTIONS-AND-OPERATORS.md (1 hunks)
  • docs/SPATIAL-TYPES.md (1 hunks)
  • docs/TEXT-AND-PATTERN-FUNCTIONS.md (1 hunks)
  • docs/USE-CASES-AND-EXAMPLES.md (6 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CollectTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TransformTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnionTest.php (1 hunks)

Walkthrough

Adds a large set of PostGIS DQL function wrappers (many new ST_* classes under Functions\PostGIS), corresponding unit and integration tests, fixture data updates (EWKT, extra rows, centralized table name), and tightens some integration assertions.

Changes

Cohort / File(s) Summary of Changes
New PostGIS function classes
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/*.php
Adds many ST_* classes (e.g., ST_3DDistance, ST_3DLength, ST_Area, ST_Buffer, ST_Distance, ST_Length, ST_Project, etc.). Each extends BaseFunction, implements protected function customizeFunction(): void, sets a SQL prototype (ST_Func(%s, ...)) and registers AST node mappings (StringPrimary, Literal, SimpleArithmeticExpression, ...).
Unit tests for wrappers
tests/Unit/.../PostGIS/ST_*Test.php
Adds unit tests for each wrapper validating DQL→SQL translation and function registration via getStringFunctions(), getExpectedSqlStatements(), and getDqlStatements().
Integration tests
tests/Integration/.../PostGIS/*Test.php
Adds many integration suites exercising geometry semantics (area, buffer, distance, length, azimuth, perimeter, Hausdorff, 3D functions, etc.) using fixtures and executeDqlQuery; covers point/line/polygon and projected‑SRID cases.
Spatial fixtures & helpers
tests/Integration/.../PostGIS/SpatialOperatorTestCase.php
Centralizes table name as TABLE_NAME, switches geometry/geography inputs to EWKT (SRID‑prefixed), and expands fixture rows (adds additional entries including a projected‑SRID row); updates table‑name usage in creation/insertion code.
Integration assertion tightenings
tests/Integration/.../PostGIS/ST_LineCrossingDirectionTest.php, .../ST_RelateMatchTest.php
Replaced non-empty assertions with exact-count assertions (assertGreaterThan(0, ...)assertCount(...)).
Test cleanup
tests/Integration/.../PostGIS/StrictlyBelowTest.php
Removes inline expectation comments; no behavioral change.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer
  participant DQL as Doctrine DQL Parser
  participant FuncNode as DQL AST FunctionNode
  participant Wrapper as BaseFunction Subclass (ST_*)
  participant SQL as SQL Renderer
  participant PG as PostGIS DB

  Dev->>DQL: Execute DQL "SELECT ST_FOO(...)"
  DQL->>FuncNode: Parse function call -> create FunctionNode
  FuncNode->>Wrapper: Use wrapper implementation
  Note right of Wrapper #D6EEF8: customizeFunction() sets\nprototype 'ST_Foo(%s, ...)'\nand node mappings
  Wrapper->>SQL: Render SQL using prototype + mapped args
  SQL->>PG: Execute "SELECT ST_Foo(...)" on PostGIS
  PG-->>SQL: Return result (numeric/geometry)
  SQL-->>Dev: Return hydrated result
  Note over Wrapper,FuncNode: Many new ST_* wrappers follow this same flow
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

enhancement, dx

Poem

"I'm a rabbit with a mapping pad,
I hop through ST_* and make tests glad.
EWKT seeds and wrappers sewn,
DQL to SQL — geometry's grown.
Hop, hop — spatial queries bloom! 🐇"

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch new-postgis-functions-2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Nitpick comments (91)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force3D.php (2)

9-22: Docblock consistency: example entity + function casing; clarify @SInCE

  • Consider aligning the DQL example with the repo’s fixtures/namespaces (ContainsGeometries) and use consistent function casing.
  • Also, please confirm whether @SInCE refers to the library version. If yes, specify the full version (e.g., 3.5.0) for clarity.
  • Optional: verify whether ST_Force3D drops an existing M dimension and reflect that nuance if accurate.
- * @example Using it in DQL: "SELECT ST_FORCE3D(g.geometry) FROM Entity g"
+ * @example Using it in DQL: "SELECT ST_Force3D(g.geometry) FROM ContainsGeometries g"
- * @since 3.5
+ * @since 3.5.0

1-31: Add a unit test covering DQL→SQL translation

Please add a test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS (e.g., ST_Force3DTest.php) mirroring existing PostGIS tests and using the ContainsGeometries fixture. Aim to assert SQL generation for a simple select and within predicates.

I can scaffold the test to match the suite’s conventions if you want.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Split.php (2)

9-22: Docblock: relax blade type statement and align example casing

The blade note is stricter than PostGIS usage (lines can split polygons; points can split linear inputs). Also, the example uses ST_SPLIT while the prototype uses ST_Split. Consider softening the statement and aligning casing.

Apply:

- * Returns a collection of geometries created by splitting the input geometry by the blade geometry.
- * The blade must be a LineString or MultiLineString.
+ * Returns a collection of geometries created by splitting the input geometry by a blade geometry.
+ * The blade is typically a LineString or MultiLineString (for polygonal inputs). For linear inputs, points can be used as a blade. See the PostGIS docs.
@@
- * @example Using it in DQL: "SELECT ST_SPLIT(g.geometry, g.blade) FROM Entity g"
+ * @example Using it in DQL: "SELECT ST_Split(g.geometry, g.blade) FROM Entity g"

23-31: Add unit test for SQL generation

Please add a PostGIS unit test mirroring existing patterns to lock the DQL→SQL translation (namespace: Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS; fixture: fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php).

I can draft ST_SplitTest.php that asserts SQL rendering for: SELECT ST_Split(g.geometry, g.blade) FROM ContainsGeometries g

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force4D.php (2)

20-21: Nit: align DQL example casing with project convention

Use “ST_Force4D” (camel-case) in the example to match other tests/docs in this repo.

- * @example Using it in DQL: "SELECT ST_FORCE4D(g.geometry) FROM Entity g"
+ * @example Using it in DQL: "SELECT ST_Force4D(g.geometry) FROM Entity g"

23-30: Add unit test for SQL rendering

Add a unit test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS validating the produced SQL (using the ContainsGeometries fixture at fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php), per existing PostGIS test patterns.

I can scaffold the test if helpful.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Perimeter.php (3)

9-22: Tighten docblock: casing consistency and scope note (geometry vs geography).

  • Use same casing as the function prototype in the example.
  • Clarify this wrapper targets the geometry signature; PostGIS also provides a geography variant with an optional use_spheroid arg.

Apply:

@@
- * @example Using it in DQL: "SELECT ST_PERIMETER(g.geometry) FROM Entity g"
- * Returns numeric perimeter value.
+ * Note: This wrapper covers the geometry signature of ST_Perimeter. The geography variant
+ * (ST_Perimeter(geography[, boolean use_spheroid])) is not supported by this node.
+ *
+ * @example Using it in DQL: "SELECT ST_Perimeter(g.geometry) FROM Entity g"
+ * Returns numeric perimeter value.

23-29: Optional: consider geography overload support.

If you plan to support ST_Perimeter(geography[, boolean use_spheroid]), you’ll need a separate node (e.g., ST_PerimeterGeography) or a parsing strategy that allows an optional second argument—current BaseFunction mapping expects a fixed arity.


9-22: Add a unit test following existing PostGIS test patterns.

Mirror the structure under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS using the ContainsGeometries fixture at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php. I can draft it if helpful.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Intersection.php (2)

9-22: Docblock nits: trim redundancy and align example casing

  • Line 21 repeats the earlier description; consider removing.
  • Example uses ST_INTERSECTION (all caps) while SQL renders ST_Intersection; pick one style across new wrappers for consistency (case-insensitive, but docs should be uniform).
  • Verify the @SInCE value (3.5) matches the planned release tag for this batch.

Happy to sweep all new PostGIS wrappers for docblock consistency in one pass if you’d like.


1-31: Add unit tests following existing PostGIS test patterns

Please add a unit test (e.g., ST_IntersectionTest) under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS mirroring the style used by ST_CrossesTest/ST_IntersectsTest and the ContainsGeometries fixture at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php.

I can scaffold the test class to match the suite’s conventions—say the word.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineToCurve.php (2)

20-21: Polish the example and cross-reference a related function.

Use canonical casing and a concrete entity used in tests; optionally add a “See also”.

- * @example Using it in DQL: "SELECT ST_LINETOCURVE(g.geometry) FROM Entity g"
- * Returns curved geometry where possible.
+ * @example Using it in DQL: "SELECT ST_LineToCurve(g.geometry) FROM ContainsGeometries g"
+ * Returns curved geometry where possible.
+ * See also: ST_CurveToLine().

23-30: Add a focused unit test mirroring existing PostGIS patterns.

Recommend a test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS that asserts DQL → SQL dispatch: SELECT ST_LineToCurve(g.geometry) FROM ContainsGeometries g renders ST_LineToCurve(…) as expected. I can draft it to follow the existing ContainsGeometries fixture usage.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Centroid.php (2)

12-16: Tighten doc accuracy: centroid is not always a midpoint / inside polygon

Current wording can mislead, especially for lines and concave polygons.

Apply:

- * Returns the geometric center of a geometry.
- * For point geometries, the centroid is the point itself.
- * For line geometries, the centroid is the midpoint.
- * For polygon geometries, the centroid is the center of mass.
+ * Returns the geometric centroid (center of mass) of the input geometry.
+ * For points, the centroid is the point itself.
+ * For lines, it is the length-weighted centroid and not necessarily the visual midpoint.
+ * For polygons, the centroid can lie outside concave shapes; prefer ST_PointOnSurface() if an interior point is required.

22-23: Make example consistent with fixtures and add alias

Per prior learnings about tests/fixtures naming, suggest using the ContainsGeometries fixture and an alias in the example.

Apply:

- * @example Using it in DQL: "SELECT ST_CENTROID(g.geometry) FROM Entity g"
- * Returns point geometry representing the centroid.
+ * @example DQL: SELECT ST_CENTROID(g.geometry) AS centroid FROM ContainsGeometries g
+ * Returns a POINT geometry representing the centroid.

If you want, I can add a unit test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_CentroidTest that mirrors existing PostGIS tests and asserts the generated SQL.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CollectionHomogenize.php (2)

9-22: Clarify @SInCE and align example casing

@SInCE 3.5” is ambiguous—likely PostGIS 3.5. Also, the example uses all-caps while the prototype is camel-case; both work, but pick one style for docs consistency.

Proposed doc tweak:

- * @since 3.5
+ * @since PostGIS 3.5
- * @example Using it in DQL: "SELECT ST_COLLECTIONHOMOGENIZE(g.geometry) FROM Entity g"
+ * @example Using it in DQL: "SELECT ST_CollectionHomogenize(g.geometry) FROM Entity g"

20-21: Add a unit test mirroring existing PostGIS tests

Add a test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS using the ContainsGeometries fixture to assert the generated SQL contains ST_CollectionHomogenize(...) per repository pattern.

I can draft ST_CollectionHomogenizeTest.php following the existing test structure. Want me to open a snippet?

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Collect.php (2)

9-22: Tighten docblock: clarify example casing and “since” tag; note arity.

  • Example casing: elsewhere functions are shown as ST_Collect; consider matching for consistency.
  • @SInCE 3.5” is unclear (library vs PostGIS). Either align to the library’s planned version or drop it.
  • This wrapper handles the 2-arg form only; call that out to avoid confusion with the aggregate 1-arg variant.

Apply this doc-only diff:

- * @see https://postgis.net/docs/ST_Collect.html
- * @since 3.5
+ * @see https://postgis.net/docs/ST_Collect.html
@@
- * @example Using it in DQL: "SELECT ST_COLLECT(g.geometry1, g.geometry2) FROM Entity g"
- * Returns geometry collection.
+ * Note: This wrapper covers the two-argument form. The aggregate one-argument form (ST_Collect(expr)) is not provided by this class.
+ *
+ * @example DQL: SELECT ST_Collect(g.geometry1, g.geometry2) FROM Entity g

25-30: Optional: add support for the aggregate single-argument variant.
If useful for GROUP BY scenarios, add a sibling wrapper for ST_Collect(expr).

Example new class (separate file) to cover the 1-arg form:

<?php
declare(strict_types=1);

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

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseFunction;

class ST_CollectAgg extends BaseFunction
{
    protected function customizeFunction(): void
    {
        $this->setFunctionPrototype('ST_Collect(%s)');
        $this->addNodeMapping('StringPrimary');
    }
}

I can also add a unit test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS following the existing ContainsGeometries fixture pattern.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force2D.php (2)

9-22: Tiny doc polish for clarity and consistency.

  • Consider noting that SRID and geometry type are preserved.
  • Keep example style consistent with other tests/docs in this repo (e.g., mention the ContainsGeometries fixture when showing DQL usage).

Apply if you like:

- * Forces the geometry into 2D mode by removing any Z or M coordinates.
- * Useful for ensuring compatibility with 2D operations.
+ * Forces the geometry into 2D mode by removing Z and M ordinates, preserving SRID and geometry type.
+ * Useful when downstream operations expect XY-only inputs.
@@
- * @example Using it in DQL: "SELECT ST_FORCE2D(g.geometry) FROM Entity g"
- * Returns 2D geometry with Z and M coordinates removed.
+ * @example DQL: SELECT ST_FORCE2D(g.geometry) FROM MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
+ * Returns a 2D geometry (XY), with Z and M ordinates removed.

23-30: Add a unit test mirroring existing PostGIS tests.

Please add a test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS, following the existing pattern (custom TestCase, ContainsGeometries fixture). Validate SQL rendering for one argument and null handling if applicable.

Happy to draft ST_Force2DTest.php matching the project’s conventions.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Boundary.php (1)

25-32: Add a focused unit test mirroring existing PostGIS tests.

Recommend a Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_BoundaryTest that asserts DQL renders to “ST_Boundary(%s)”.

I can draft the test file following the ContainsGeometries fixture and existing test patterns—want me to add it?

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Extrude.php (1)

20-21: Doc example: fix function casing and align entity name with fixtures.

Use ST_Extrude (consistent with prototype) and the ContainsGeometries fixture per existing tests.

- * @example Using it in DQL: "SELECT ST_EXTRUDE(g.geometry, 0, 0, 10) FROM Entity g"
- * Returns 3D extruded geometry.
+ * @example Using it in DQL: "SELECT ST_Extrude(g.geometry, 0, 0, 10) FROM ContainsGeometries g"
+ * Returns a 3D extruded geometry.
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ConvexHull.php (3)

20-21: Tighten the doc example and keep casing consistent

Use the concrete fixture entity and match the mixed-case function name used in the prototype.

- * @example Using it in DQL: "SELECT ST_CONVEXHULL(g.geometry) FROM Entity g"
- * Returns convex hull geometry.
+ * @example Using it in DQL: "SELECT ST_ConvexHull(g.geometry) FROM ContainsGeometries g"
+ * Returns the convex hull geometry.

23-23: Consider marking the class final

These wrappers are not intended for inheritance; making the class final clarifies intent and can slightly help static analysis.

-class ST_ConvexHull extends BaseFunction
+final class ST_ConvexHull extends BaseFunction

9-22: Add a unit test mirroring existing PostGIS tests

Recommend a test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS validating DQL→SQL translation using the ContainsGeometries fixture (as in prior tests).

I can draft ST_ConvexHullTest.php following the established pattern if you want.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Transform.php (3)

29-29: Option: allow parameterized SRID (e.g., :srid) instead of only literals.

Using ArithmeticPrimary enables bound params and expressions while still supporting integers.

Apply this diff if you want param support:

-        $this->addNodeMapping('Literal');
+        $this->addNodeMapping('ArithmeticPrimary');

Ensure this aligns with conventions across other numeric-arg PostGIS wrappers in this repo before changing.


20-21: Docblock example/style nits.

Minor polish for consistency: prefer ST_Transform casing and (optionally) use the ContainsGeometries fixture used in tests.

Apply this doc tweak:

- * @example Using it in DQL: "SELECT ST_TRANSFORM(g.geometry, 4326) FROM Entity g"
- * Returns transformed geometry in the specified SRID.
+ * @example DQL: SELECT ST_Transform(g.geometry, 4326) FROM ContainsGeometries g

25-30: Optional: support the 3-argument variant (to_srid, from_srid).

PostGIS also supports ST_Transform(geom, to_srid, from_srid). Consider a separate wrapper to keep fixed-arity parsing simple.

Example new class (add as a separate file):

<?php
declare(strict_types=1);

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

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseFunction;

/**
 * Implementation of PostGIS ST_Transform(geom, to_srid, from_srid).
 */
class ST_TransformFromTo extends BaseFunction
{
    protected function customizeFunction(): void
    {
        $this->setFunctionPrototype('ST_Transform(%s, %s, %s)');
        $this->addNodeMapping('StringPrimary');
        $this->addNodeMapping('Literal');
        $this->addNodeMapping('Literal');
    }
}

Want me to add tests mirroring the existing PostGIS test pattern?

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifference.php (2)

20-22: Fix DQL example: use canonical casing and real fixture entity.

Use ST_SymDifference (camel-case) and the ContainsGeometries fixture to mirror existing tests.

Apply this docblock tweak:

- * @example Using it in DQL: "SELECT ST_SYMDIFFERENCE(g1.geometry, g2.geometry) FROM Entity g1, Entity g2"
- * Returns geometry representing the symmetric difference.
+ * @example Using it in DQL: "SELECT ST_SymDifference(g1.geometry, g2.geometry) FROM ContainsGeometries g1, ContainsGeometries g2"
+ * Returns a geometry representing the symmetric difference.

23-31: Add a unit test mirroring existing PostGIS tests.

Please add Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_SymDifferenceTest using the ContainsGeometries fixture, asserting correct SQL generation and parameters.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistance.php (3)

25-30: Consider adding a 3rd-argument variant for densifyFrac.

PostGIS exposes an overload with a densification fraction; a separate DQL wrapper would preserve BaseFunction’s fixed-arity pattern.

Example new class (separate file) to support the 3-arg overload:

<?php
declare(strict_types=1);

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

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseFunction;

/**
 * Implementation of PostGIS ST_FrechetDistance(geom1, geom2, densifyFrac) overload.
 */
final class ST_FrechetDistanceDensify extends BaseFunction
{
    protected function customizeFunction(): void
    {
        $this->setFunctionPrototype('ST_FrechetDistance(%s, %s, %s)');
        $this->addNodeMapping('StringPrimary');
        $this->addNodeMapping('StringPrimary');
        $this->addNodeMapping('ArithmeticPrimary'); // densifyFrac
    }
}

9-22: Tighten docblock: call out supported overload and verify @SInCE.

Add a note that this wrapper wires the 2-arg geometry overload; the densify overload (if added) should be referenced separately. Also please confirm that “@SInCE 3.5” refers to the library’s version.

@@
  /**
   * Implementation of PostGIS ST_FrechetDistance() function.
   *
   * Returns the Fréchet distance between two geometries.
   * This is a measure of similarity between curves that takes into account the location and ordering of points.
   *
   * @see https://postgis.net/docs/ST_FrechetDistance.html
- * @since 3.5
+ * @since 3.5
+ *
+ * Note: This DQL wrapper wires the 2-argument geometry overload.
+ * For the densifyFrac overload, use a dedicated wrapper (e.g. ST_FrechetDistanceDensify).
@@
- * @example Using it in DQL: "SELECT ST_FRECHETDISTANCE(g1.geometry, g2.geometry) FROM Entity g1, Entity g2"
+ * @example Using it in DQL: "SELECT ST_FRECHETDISTANCE(g1.geometry, g2.geometry) FROM Entity g1, Entity g2"
   * Returns numeric Fréchet distance value.
   */

23-31: Add a unit test to lock translation.

Please add a test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistent with existing patterns and using the ContainsGeometries fixture at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php.

I can draft ST_FrechetDistanceTest.php mirroring other PostGIS tests if helpful.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Reverse.php (3)

9-23: Docblock polish: broaden type notes and trim duplication

Tighten wording, note Multi* behavior, and drop the duplicate summary line.

- * Returns a geometry with the order of points reversed.
- * For LineString, the start and end points are swapped.
- * For Polygon, the ring orientations are reversed.
+ * Returns a geometry with vertices in reversed order.
+ * LineString/MultiLineString: reverses vertex order (start/end swap).
+ * Polygon/MultiPolygon: reverses ring orientations.
@@
- * @example Using it in DQL: "SELECT ST_REVERSE(g.geometry) FROM Entity g"
- * Returns geometry with reversed point order.
+ * @example DQL: SELECT ST_REVERSE(g.geometry) FROM Entity g

17-17: Clarify @SInCE target

If this refers to the library version, consider “@SInCE 3.5.0” (or the exact tag you plan to release). If it’s PostGIS’ version, specify “@SInCE PostGIS 3.5”.


24-31: Add ST_ReverseTest for PostGIS function
Create a new test at Tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ReverseTest.php that mirrors existing tests (e.g. ST_CrossesTest). Extend AbstractFunctionalTest, load the MartinGeorgiev\Doctrine\Entity\ContainsGeometries fixture (fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php), and assert that the DQL for ST_Reverse generates the correct SQL prototype (ST_Reverse(%s)). I can draft the test if helpful.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Rotate.php (4)

9-22: Docblock: verify @SInCE and tighten example.

  • Please confirm the library version in the @SInCE tag ("3.5") is accurate for this PR.
  • Optional: add a parameterized DQL example (e.g., ST_ROTATE(g.geometry, :angle)) if you intend to support parameters in the angle position.

25-30: Potential second signature (rotate about a point).

PostGIS also supports rotation about a point. BaseFunction’s fixed node mapping doesn’t allow optional args, so if you plan to support that variant, you’ll likely need a separate wrapper mapping to ST_Rotate with four args. I can draft it to match existing naming patterns if you confirm the preferred DQL name.


9-22: Add a unit test following existing PostGIS test patterns.

Recommend adding Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_RotateTest using the ContainsGeometries fixture (per existing repo patterns). Happy to scaffold it.

Note: Leveraged your past preference about test structure and fixtures from prior PRs.


25-30: Use ArithmeticPrimary for angle parameter to enable parameters and arithmetic
Switch the node mapping from Literal to ArithmeticPrimary—this aligns with other PostGIS wrappers (e.g. ST_DWithin, ST_PointInsideCircle) and allows expressions like :angle or 3.14/2. Optional refactor:

-        $this->addNodeMapping('Literal');
+        $this->addNodeMapping('ArithmeticPrimary');
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Project.php (2)

10-22: Fix example and clarify units (azimuth is in radians).

PostGIS expects azimuth (bearing) in radians and distance in meters. Update the example and mention the units to prevent misuse. Also, use ST_Project casing for consistency with docs.

  /**
   * Implementation of PostGIS ST_Project() function.
   *
- * Projects a point along a geodesic.
- * Useful for calculating positions along great circle paths.
+ * Projects a point along a geodesic. Distance is in meters; azimuth (bearing) is in radians.
+ * Useful for calculating positions along great circle paths.
   *
   * @see https://postgis.net/docs/ST_Project.html
   * @since 3.5
   *
   * @author Martin Georgiev <martin.georgiev@gmail.com>
   *
- * @example Using it in DQL: "SELECT ST_PROJECT(g.geometry, 1000, 45) FROM Entity g"
+ * @example Using it in DQL: "SELECT ST_Project(g.geometry, 1000, radians(45.0)) FROM Entity g"
   * Returns projected point.
  */

References: azimuth in radians; example with radians(); geometry variant available since PostGIS 3.4.0. (postgis.net)


27-27: Consider exposing the two-point overload of ST_Project.

PostGIS also supports ST_Project(g1, g2, distance) (two-point form, no azimuth). If useful for callers, add a sibling wrapper (e.g., ST_ProjectFrom or ST_Project2Points) with prototype ST_Project(%s, %s, %s) and node mappings [StringPrimary, StringPrimary, SimpleArithmeticExpression].

Reference: two-point overload exists. (postgis.net)

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLine.php (3)

9-22: Docblock: clarify supported arities and verify @SInCE.

  • PostGIS supports optional args (tolerance, tolerance_type, flags). Either note this wrapper currently covers only the 1-arg form or extend support; also please confirm the correct library version for @SInCE. (postgis.net)

Suggested doc tweak (minimal):

 /**
  * Implementation of PostGIS ST_CurveToLine() function.
  *
- * Converts curved geometries to linear geometries.
- * Useful for converting CircularString, CompoundCurve, etc. to LineString.
+ * Converts curved geometries to linear geometries.
+ * Useful for converting CircularString, CompoundCurve, etc. to LineString.
+ *
+ * Note: PostGIS also supports optional parameters
+ * (tolerance [, tolerance_type [, flags]]). This wrapper currently
+ * implements the single-argument variant.
  *
- * @see https://postgis.net/docs/ST_CurveToLine.html
- * @since 3.5
+ * @see https://postgis.net/docs/en/ST_CurveToLine.html
+ * @since 3.5
  *
  * @author Martin Georgiev <martin.georgiev@gmail.com>
  *
  * @example Using it in DQL: "SELECT ST_CURVETOLINE(g.geometry) FROM Entity g"
  * Returns linear geometry.
  */

Would you like a follow-up PR to add 2/3/4-arg variants?


25-29: Function mapping is correct for the 1-arg prototype.

  • Prototype and node mapping match the intended usage; no parsing pitfalls.

If you plan to support additional arities later, we can introduce separate wrappers (e.g., ST_CurveToLine2, ST_CurveToLine3, ST_CurveToLine4) or extend BaseFunction to handle optional nodes across this family of functions.


9-22: Add a unit test mirroring existing PostGIS test patterns.

  • Add Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_CurveToLineTest covering DQL→SQL rendering against the ContainsGeometries fixture, consistent with existing PostGIS tests in this repo.

I can scaffold the test file following the established namespace and fixture usage.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CollectionExtract.php (4)

29-29: Consider allowing bind parameters for the type argument.

Using a numeric Literal prohibits DQL parameters (e.g., :type). If you want parameterization, parse a simple arithmetic expression instead.

-        $this->addNodeMapping('Literal');
+        $this->addNodeMapping('SimpleArithmeticExpression');

20-21: Casing consistency in example.

DQL is case-insensitive, but consider using “ST_CollectionExtract(…)” to mirror the function name used in this class and other docs.


12-14: Optional: document accepted geometry type codes.

Adding a brief note about valid “type” values improves DX without requiring a docs hop.


23-31: Add a unit test aligned with existing PostGIS tests.

Please add a test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS asserting correct SQL generation with ContainsGeometries (fixture at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php).

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistance.php (3)

27-29: Consider optional third parameter (densifyFrac).

PostGIS supports ST_HausdorffDistance(g1, g2, densifyFrac FLOAT) with an optional third argument. If you want that coverage, options:

  • Minimal: add a separate DQL function (e.g., ST_HausdorffDistanceDensify) that maps three args.
  • Broader: extend BaseFunction to support optional trailing nodes, then accept 2 or 3 args here.

Example of a dedicated 3-arg wrapper (new file):

<?php
declare(strict_types=1);

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

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseFunction;

final class ST_HausdorffDistanceDensify extends BaseFunction
{
    protected function customizeFunction(): void
    {
        $this->setFunctionPrototype('ST_HausdorffDistance(%s, %s, %s)');
        $this->addNodeMapping('StringPrimary'); // g1
        $this->addNodeMapping('StringPrimary'); // g2
        $this->addNodeMapping('Literal');       // densifyFrac
    }
}

20-21: Doc example: align to repo fixtures (nit).

To mirror existing tests/docs, consider using the ContainsGeometries fixture in the example:
SELECT ST_HAUSDORFFDISTANCE(g1.geometry, g2.geometry) FROM ContainsGeometries g1, ContainsGeometries g2


23-31: Add unit tests similar to other PostGIS wrappers.

Follow the pattern in Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS using the ContainsGeometries fixture at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php. Include cases for:

  • Two-argument form (g1, g2).
  • If you add the densify variant, a three-argument form.

I can draft the test file if helpful.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2D.php (2)

21-21: Align example casing with function prototype.

Use ST_Length2D (mixed case) for consistency with the generated SQL.

- * @example Using it in DQL: "SELECT ST_LENGTH2D(g.geometry) FROM Entity g"
+ * @example Using it in DQL: "SELECT ST_Length2D(g.geometry) FROM Entity g"

24-31: Add a unit test mirroring existing PostGIS tests.

Recommend adding Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Length2DTest to assert DQL-to-SQL rendering, following the pattern used in other PostGIS tests and the ContainsGeometries fixture. I can scaffold it if you’d like.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2D.php (2)

20-21: Doc example: align casing with function name and typical usage.

Use ST_ClipByBox2D (CamelCase) in the example to stay consistent with the class and other docs. Optionally, demonstrate a box2d-producing expression to reflect real-world usage.

- * @example Using it in DQL: "SELECT ST_CLIPBYBOX2D(g.geometry, 'BOX(0 0, 100 100)') FROM Entity g"
+ * @example Using it in DQL: "SELECT ST_ClipByBox2D(g.geometry, 'BOX(0 0, 100 100)') FROM Entity g"
+ * @example With expression: "SELECT ST_ClipByBox2D(g.geometry, ST_Extent(g.geometry)) FROM Entity g GROUP BY g.geometry"

9-22: Add unit tests mirroring existing PostGIS test patterns.

Please add a unit test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ (use the ContainsGeometries fixture as in other tests) to cover:

  • literal BOX argument
  • expression/parameter argument (enabled by switching to StringPrimary)

I can scaffold ST_ClipByBox2DTest.php following the existing suite if you’d like.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Scale.php (5)

25-31: Confirm intended signature coverage for ST_Scale

This wrapper implements only ST_Scale(geom, x, y). PostGIS also supports (geom, x, y, z) and the geometry factor and optional origin variants. If broader coverage is desired, consider adding separate wrappers (e.g., ST_Scale3D, ST_ScaleWithFactor, ST_ScaleWithOrigin). (postgis.net)


28-31: Allow parameterized factors (:x, :y) instead of only literals

If you want DQL params or expressions, switch the parser nodes from Literal to SimpleArithmeticExpression.

Apply this diff if consistent with the codebase:

-        $this->addNodeMapping('Literal');
-        $this->addNodeMapping('Literal');
+        $this->addNodeMapping('SimpleArithmeticExpression');
+        $this->addNodeMapping('SimpleArithmeticExpression');

15-17: Clarify or remove ambiguous @SInCE tag

@SInCE 3.5” is unclear (PostGIS 3.5 docs vs. library version). Either remove it or specify the product/version explicitly.

Apply one of the following:

- * @since 3.5

or

- * @since 3.5
+ * @since PostGIS 1.1.0 (function available); enhanced in 2.5.0 to support local origin.

(postgis.net, postgis.net)


20-21: Tweak DQL example for consistency with test fixtures

Use the known fixture/entity name and consistent casing.

Apply:

- * @example Using it in DQL: "SELECT ST_SCALE(g.geometry, 2, 2) FROM Entity g"
+ * @example Using it in DQL: "SELECT ST_Scale(g.geometry, 2, 2) FROM ContainsGeometries g"

1-32: Add a focused unit test

Please add Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_ScaleTest exercising DQL generation for (geom, x, y), following the pattern used in other PostGIS tests (ContainsGeometries fixture). I can scaffold it if helpful.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistance.php (2)

20-21: Polish example and return-type wording for accuracy and consistency

Align the example with repository conventions (CamelCase function name) and an existing fixture name; tighten the return-type wording.

- * @example Using it in DQL: "SELECT ST_MAXDISTANCE(g1.geometry, g2.geometry) FROM Entity g1, Entity g2"
- * Returns numeric maximum distance value.
+ * @example Using it in DQL: "SELECT ST_MaxDistance(g1.geometry, g2.geometry) FROM ContainsGeometries g1, ContainsGeometries g2"
+ * Returns double precision maximum distance value.

Note: I’m referencing the ContainsGeometries fixture and test namespace pattern from prior learnings for this repo.


23-31: Add a unit test mirroring existing PostGIS function tests

Add ST_MaxDistanceTest under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS, following the same style as other PostGIS tests (e.g., ST_CrossesTest). Aim to assert DQL-to-SQL translation rather than numeric evaluation.

If you want, I can draft the test file to match the established pattern and wire it into the suite.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnion.php (2)

25-29: Consider supporting the optional gridSize argument (2nd param).

PostGIS ST_UnaryUnion accepts an optional float8 gridSize (since PostGIS 3.1 / GEOS ≥ 3.9). If feasible within your BaseFunction constraints, consider allowing 1 or 2 args; otherwise, document that only the 1-arg variant is supported. (postgis.net)

How do we usually model optional trailing args in this library? If we keep fixed arity, I suggest explicitly documenting the limitation (see next comment’s diff).


9-22: Polish the docblock: clarify behavior, fix example casing, and note arity.

  • Clarify description (single-input variant of ST_Union).
  • Use consistent function casing in the example (matches other docs).
  • Optionally note that this wrapper supports only the 1-argument signature for now.

Apply:

@@
 /**
  * Implementation of PostGIS ST_UnaryUnion() function.
  *
- * Performs unary union on a geometry.
- * Useful for dissolving internal boundaries in polygons.
+ * Computes the union of the components of a single geometry (single-input variant of ST_Union).
+ * Useful for dissolving internal boundaries in polygons and fixing overlapping multipolygons.
+ * Note: this wrapper currently implements the 1-argument signature. The gridSize variant (PostGIS 3.1+) is not yet supported.
@@
- * @example Using it in DQL: "SELECT ST_UNARYUNION(g.geometry) FROM Entity g"
- * Returns unioned geometry.
+ * @example Using it in DQL: "SELECT ST_UnaryUnion(g.geometry) FROM ContainsGeometries g"
+ * Returns the unioned geometry.

Reference for optional gridSize: PostGIS manual. (postgis.net)

If you want, I can add a matching unit test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_UnaryUnionTest that follows the existing ContainsGeometries fixture pattern.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Subdivide.php (3)

12-16: Confirm the version in @SInCE.

ST_Subdivide predates PostGIS 3.5. Please either remove the @since tag or set it to the correct original version.

- * @since 3.5
+ * @since TBD — verify actual PostGIS introduction version or remove this tag

25-30: Signature covers only 2 params; consider grid-align variant and parameterization.

  • PostGIS supports an optional 3rd boolean gridalign. If you plan to expose it, this base parser doesn’t support optional args—consider a companion class (e.g., ST_SubdivideGridAlign) or a separate 3-arg variant.
  • If you want to allow bound parameters for maxvertices (instead of only literals), consider ArithmeticPrimary or InputParameter per project conventions.

Examples:

-        $this->addNodeMapping('Literal');
+        $this->addNodeMapping('Literal'); // or 'ArithmeticPrimary' to accept parameters

and optionally a separate 3-arg wrapper:

// class ST_SubdivideGridAlign extends BaseFunction { prototype 'ST_Subdivide(%s, %s, %s)'; mappings: StringPrimary, Literal, Literal }

1-31: Add unit tests mirroring existing PostGIS test patterns.

Please add a unit test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS that matches the suite’s structure (see prior PostGIS tests and the ContainsGeometries fixture path noted in learnings). Focus on verifying SQL generation; if SRF/LATERAL is out-of-scope for DQL, document and test via NativeQuery.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Translate.php (2)

27-31: Consider a 2D convenience wrapper to mirror PostGIS’ 2- and 3-arg forms.

Current mapping requires DZ. If you want ergonomic 2D usage without forcing a third arg, add a companion wrapper that defaults DZ=0.

Example new class (outside this file):

<?php
declare(strict_types=1);

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

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseFunction;

final class ST_Translate2D extends BaseFunction
{
    protected function customizeFunction(): void
    {
        $this->setFunctionPrototype('ST_Translate(%s, %s, 0)');
        $this->addNodeMapping('StringPrimary'); // geometry
        $this->addNodeMapping('Literal');       // dx, dy combined via two wrappers is not supported, so 2D == dz=0
    }
}

Alternatively, if you prefer not to add a class, keeping the current 3-arg form is fine once the doc is corrected.


23-32: Add unit tests for both 2D-via-DZ=0 and 3D cases.

Follow existing PostGIS test patterns and fixtures to ensure the DQL-to-SQL translation is correct.

Per prior learnings, place tests under:

  • Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_TranslateTest.php
    and use the ContainsGeometries fixture at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php.
    Want me to draft the test skeleton?
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Difference.php (2)

9-22: Confirm @SInCE value and doc example consistency.
Please verify that “@SInCE 3.5” matches the planned library release. Keep examples consistently uppercased in DQL if that’s the convention.


1-31: Add unit tests following existing PostGIS test patterns.
Recommend adding a test under Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS verifying SQL generation for ST_DIFFERENCE(a.geom, b.geom) using the ContainsGeometries fixture.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DLength.php (2)

12-14: Verify accuracy of the areal-geometry note.
PostGIS usually separates 3D length (lines) from 3D perimeter (areal). Please double-check whether ST_3DLength returns perimeter for areal geometries; adjust text if needed.


1-31: Add unit tests for SQL generation.
Include tests asserting ST_3DLENGTH(g.geometry) renders as expected, mirroring the structure used by other ST_* tests.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DPerimeter.php (2)

12-14: Confirm return behavior for non-areal geometries.
Please verify that ST_3DPerimeter returns 0 (and not NULL or an error) for non-areal geometries per PostGIS docs.


1-31: Add unit tests mirroring existing PostGIS suite.
Test that ST_3DPERIMETER(g.geometry) compiles correctly and returns numeric context.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (2)

25-29: Consider supporting the geography overload.
PostGIS allows ST_Area(geography, use_spheroid boolean). Consider adding a 2-arg wrapper to cover this use case.


1-31: Add unit tests.
Provide tests ensuring ST_AREA(g.geometry) is emitted as expected, following the established test namespace and fixtures.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Azimuth.php (2)

12-14: Clarify range and inputs in docs (optional).
You may note the return range [0, 2π) and that inputs should be POINT geometries to reduce ambiguity.


1-31: Add unit tests.
Add a test asserting SQL generation for ST_AZIMUTH(p1.geom, p2.geom), consistent with other PostGIS tests.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Union.php (1)

25-30: Add a one-argument aggregate wrapper for ST_Union

Doctrine can’t overload by arity; consider a separate DQL function (e.g., ST_UnionAgg) for the aggregate form ST_Union(expr).

Example new file:

<?php
declare(strict_types=1);

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

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseFunction;

/**
 * Aggregate variant of PostGIS ST_Union(expr).
 */
class ST_UnionAgg extends BaseFunction
{
    protected function customizeFunction(): void
    {
        $this->setFunctionPrototype('ST_Union(%s)');
        $this->addNodeMapping('StringPrimary');
    }
}
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyVW.php (1)

27-29: Allow parameters/expressions for tolerance

Use SimpleArithmeticExpression so callers can pass bound params or arithmetic, not only literals.

Apply:

-        $this->addNodeMapping('Literal');
+        $this->addNodeMapping('SimpleArithmeticExpression');

If the codebase standardizes on Literal for numeric args, keep as-is; otherwise align similar functions in this PR.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Buffer.php (2)

27-29: Permit parameterized distance

Swap Literal with SimpleArithmeticExpression to support bound params/expressions for distance.

-        $this->addNodeMapping('Literal');
+        $this->addNodeMapping('SimpleArithmeticExpression');

Confirm consistency with other numeric-arg wrappers you prefer in this library.


25-30: Consider a 3-arg/style-params variant

PostGIS supports ST_Buffer(geom, dist, nQuadSegs|styleText). Since overloading isn’t available in DQL registration, add a distinct wrapper (e.g., ST_Buffer3 or ST_BufferParams) if you want that coverage.

Example:

class ST_Buffer3 extends BaseFunction
{
    protected function customizeFunction(): void
    {
        $this->setFunctionPrototype('ST_Buffer(%s, %s, %s)');
        $this->addNodeMapping('StringPrimary');
        $this->addNodeMapping('SimpleArithmeticExpression'); // distance
        $this->addNodeMapping('Literal'); // nQuadSegs or style text
    }
}

Happy to add unit tests mirroring existing PostGIS test patterns for these variants.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistance.php (1)

20-21: Nit: keep example casing consistent.

Elsewhere examples use function/method names in their canonical/mixed case. Consider “SELECT ST_3DDistance(g1.geometry, g2.geometry) …”.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyPreserveTopology.php (3)

27-30: Allow parameters/expressions for tolerance.

Using Literal prevents passing DQL parameters (e.g., :tolerance) or arithmetic. ArithmeticPrimary aligns with similar functions (e.g., ST_3DDWithin’s distance).

Apply:

-        $this->addNodeMapping('Literal');
+        $this->addNodeMapping('ArithmeticPrimary');

If other simplification/measurement wrappers in this PR accept parameters (ArithmeticPrimary), consider standardizing across them for consistency.


20-21: Nit: example could show parameterized usage.

E.g., “… ST_SimplifyPreserveTopology(g.geometry, :tolerance) …” (useful once ArithmeticPrimary is adopted).


23-30: Add unit tests following existing PostGIS test patterns.

Please add Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_SimplifyPreserveTopologyTest covering literal and parameterized tolerance. The ContainsGeometries fixture lives at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php (per prior repo patterns).

I can scaffold the test to match the suite’s conventions if helpful.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)

9-22: Optional: clarify scope or add a geography variant.

ST_Length on geography accepts an optional boolean “use_spheroid”. If you plan to support geography, consider a dedicated wrapper with two args, or clarify in the docblock that this wrapper targets geometry only.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DArea.php (1)

12-14: Doc nit: use PostGIS geometry type names (capitalization)
Use “Polygon” and “MultiPolygon” to match PostGIS docs.

- * Returns the 3D area of the geometry if it is a polygon or multi-polygon.
+ * Returns the 3D area of the geometry if it is a Polygon or MultiPolygon.

Comment on lines 25 to 32
protected function customizeFunction(): void
{
$this->setFunctionPrototype('ST_Extrude(%s, %s, %s, %s)');
$this->addNodeMapping('StringPrimary');
$this->addNodeMapping('Literal');
$this->addNodeMapping('Literal');
$this->addNodeMapping('Literal');
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Allow parameters and expressions for dx/dy/dz (use SimpleArithmeticExpression, not Literal).

Using Literal prevents passing placeholders like :dx, ?1 or arithmetic. Other wrappers typically use SimpleArithmeticExpression for numeric args.

Apply:

     protected function customizeFunction(): void
     {
         $this->setFunctionPrototype('ST_Extrude(%s, %s, %s, %s)');
         $this->addNodeMapping('StringPrimary');
-        $this->addNodeMapping('Literal');
-        $this->addNodeMapping('Literal');
-        $this->addNodeMapping('Literal');
+        $this->addNodeMapping('SimpleArithmeticExpression');
+        $this->addNodeMapping('SimpleArithmeticExpression');
+        $this->addNodeMapping('SimpleArithmeticExpression');
     }
🤖 Prompt for AI Agents
In src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Extrude.php
around lines 25 to 32, the node mappings for the dx/dy/dz parameters use
'Literal' which prevents placeholders and arithmetic; replace the three
addNodeMapping('Literal') calls with
addNodeMapping('SimpleArithmeticExpression') so those parameters accept
expressions and parameter placeholders (leave the function prototype and the
StringPrimary mapping as-is).

Comment on lines 12 to 15
* Returns the 2D length of the geometry if it is a LineString or MultiLineString.
* For areal geometries, the 2D perimeter is returned.
* Ignores Z coordinates.
*
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 doc: areal geometries behavior and alias note.

ST_Length2D returns 0 for areal geometries (use ST_Perimeter for perimeters) and is an alias of ST_Length. Update the docblock accordingly.

- * Returns the 2D length of the geometry if it is a LineString or MultiLineString.
- * For areal geometries, the 2D perimeter is returned.
- * Ignores Z coordinates.
+ * Returns the 2D length of the geometry if it is a LineString or MultiLineString.
+ * For areal geometries, 0 is returned; use ST_Perimeter for polygonal perimeters.
+ * Ignores Z coordinates.
+ * Alias of ST_Length.

Reference: PostGIS docs for ST_Length2D and ST_Length. (postgis.net, postgis.net)

📝 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
* Returns the 2D length of the geometry if it is a LineString or MultiLineString.
* For areal geometries, the 2D perimeter is returned.
* Ignores Z coordinates.
*
* Returns the 2D length of the geometry if it is a LineString or MultiLineString.
* For areal geometries, 0 is returned; use ST_Perimeter for polygonal perimeters.
* Ignores Z coordinates.
* Alias of ST_Length.
*

Comment on lines +20 to +21
* @example Using it in DQL: "SELECT ST_SUBDIVIDE(g.geometry, 256) FROM Entity g"
* Returns set of subdivided geometries.
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Doc example is invalid for PostgreSQL 10+ (SRF in SELECT list).

ST_Subdivide is set-returning; it must be used via LATERAL. The current DQL example will compile to invalid SQL on supported PostgreSQL versions and could mislead users. Replace with a LATERAL SQL example and clarify DQL limitations (likely requires NativeQuery or a DB view).

Apply:

- * @example Using it in DQL: "SELECT ST_SUBDIVIDE(g.geometry, 256) FROM Entity g"
- * Returns set of subdivided geometries.
+ * Note: ST_Subdivide is set-returning. PostgreSQL 10+ forbids SRFs in the SELECT list.
+ * Example (SQL): SELECT g.id, s.geom FROM my_table g
+ *   CROSS JOIN LATERAL ST_Subdivide(g.geometry, 256) AS s(geom);
+ * Doctrine ORM: DQL cannot express LATERAL; use a NativeQuery or a view when needed.

To verify SRF/LATERAL support in this library:


🏁 Script executed:

#!/bin/bash
rg -n -C2 -e 'CROSS\s+JOIN\s+LATERAL|JOIN\s+LATERAL|\\bLATERAL\\b' -e 'SetReturning|TableValued|FromFunction' src
rg -n -C2 'class\s+ST_Dump\b' src || true
rg -n -C2 'LATERAL|ST_Subdivide' tests || true

Length of output: 206


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Subdivide.php

Length of output: 997


Replace invalid DQL example in ST_Subdivide docblock with SQL LATERAL example and disclaimer
ST_Subdivide returns a set of geometries; PostgreSQL 10+ forbids SRFs in the SELECT list and DQL cannot express LATERAL, so update the docblock accordingly.

--- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Subdivide.php
+++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Subdivide.php
@@ -17,8 +17,11 @@
  * @since 3.5
  *
  * @author Martin Georgiev <martin.georgiev@gmail.com>
- *
- * @example Using it in DQL: "SELECT ST_SUBDIVIDE(g.geometry, 256) FROM Entity g"
- * Returns set of subdivided geometries.
+ * Note: ST_Subdivide is set-returning; PostgreSQL 10+ forbids SRFs in the SELECT list.
+ * Example (SQL):
+ *   SELECT g.id, s.geom
+ *     FROM my_table g
+ *   CROSS JOIN LATERAL ST_Subdivide(g.geometry, 256) AS s(geom);
+ * Doctrine ORM: DQL cannot express LATERAL; use a NativeQuery or a view.
  */
 class ST_Subdivide extends BaseFunction
 {
🤖 Prompt for AI Agents
In src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Subdivide.php
around lines 20-21, the docblock currently shows an invalid DQL example using
ST_SUBDIVIDE in the SELECT list; replace that DQL example with a SQL example
showing use via LATERAL (for example: SELECT (ST_SUBDIVIDE(g.geometry, 256)).*
FROM my_table g, LATERAL ST_SUBDIVIDE(g.geometry, 256) s) and add a brief
disclaimer that ST_Subdivide returns a set of geometries, PostgreSQL 10+ forbids
set-returning functions in the SELECT list and DQL cannot express LATERAL, so
users must use native SQL or handle the set via lateral joins or unnesting.

Comment on lines +12 to +14
* Translates a geometry by the given offsets.
* Moves the geometry in X, Y, and optionally Z directions.
*
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 doc/example: implementation enforces 3 args, example shows 2 (will parse-error).

Either support optional DZ in the parser, or update the doc to reflect the required 3-argument signature and show 2D via DZ=0.

Apply this doc tweak if keeping the 3-arg signature:

- * Moves the geometry in X, Y, and optionally Z directions.
+ * Moves the geometry in X, Y, and Z directions (pass 0 for Z to perform a 2D translation).
...
- * @example Using it in DQL: "SELECT ST_TRANSLATE(g.geometry, 10, 20) FROM Entity g"
+ * @example Using it in DQL (2D): "SELECT ST_TRANSLATE(g.geometry, 10, 20, 0) FROM Entity g"
+ * @example Using it in DQL (3D): "SELECT ST_TRANSLATE(g.geometry, 10, 20, 5) FROM Entity g"

Also applies to: 20-21

🤖 Prompt for AI Agents
In src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Translate.php
around lines 12-14 (and also lines 20-21), the doc/example states a 2-argument
usage while the implementation enforces 3 arguments which causes a parse error;
update the documentation to reflect the actual required 3-argument signature and
change the example to show a 2D translation by passing DZ=0 (e.g.,
ST_Translate(geom, dx, dy, 0)) OR alternatively modify the parser/argument
validation to accept an optional third DZ argument and handle the missing value
as 0 — pick one approach and make the corresponding code or doc change so doc
and implementation are consistent.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (48)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php (1)

26-31: Optional: add an integration-style case with a WKT literal.

Consider complementing unit coverage with an integration test using a WKT literal argument to confirm end-to-end translation and implicit geometry coercion (kept out of unit suite to follow the project’s testing focus).

I can draft the additional integration test if helpful.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CentroidTest.php (1)

26-31: DQL statement is valid and uses the correct fixture path/property.
Optional: add a second case using a WKT literal to cover literal-argument parsing for StringPrimary without relying on another wrapper.

Apply this diff to extend coverage with a literal input variant:

     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_Centroid(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+            "SELECT ST_Centroid('POINT(-5 -5)') AS sclr_0 FROM ContainsGeometries c0_",
         ];
     }

     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_CENTROID(g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            "SELECT ST_CENTROID('POINT(-5 -5)') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g",
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IntersectionTest.php (1)

19-24: Optional: add a second case with reversed operands for extra coverage

This slightly broadens coverage without introducing DB semantics, ensuring both positional arguments are handled identically by the translator.

Apply the diffs below to append an extra pair:

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_Intersection(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Intersection(c0_.geometry2, c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_INTERSECTION(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_INTERSECTION(g.geometry2, g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }

Also applies to: 26-31

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLineTest.php (1)

12-17: Optional: consider future overload coverage

If you decide to expose additional parameters/overloads for ST_CurveToLine in the wrapper, add companion test cases here with extra DQL/SQL pairs.

Happy to draft the wrapper and tests when you’re ready.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DifferenceTest.php (1)

19-24: Optionally add a WKT-literal case to broaden coverage

Covers StringLiteral input and order sensitivity; add a second pair to both arrays.

     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_Difference(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Difference(\'POINT(0 0)\', c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }

     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_DIFFERENCE(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_DIFFERENCE(\'POINT(0 0)\', g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }

Also applies to: 26-31

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_EnvelopeTest.php (1)

19-31: Optional: add a literal-WKT case to broaden coverage of StringPrimary.

Since the wrapper accepts StringPrimary, a second scenario with a WKT literal would strengthen coverage without coupling to PostGIS behavior.

Apply this diff to append an additional case:

     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_Envelope(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+            "SELECT ST_Envelope('POINT(-5 -5)') AS sclr_0 FROM ContainsGeometries c0_",
         ];
     }

     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_ENVELOPE(g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            "SELECT ST_ENVELOPE('POINT(-5 -5)') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g",
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CollectTest.php (1)

26-31: Optional: add a literal+column case for broader coverage.

Consider a second pair to assert handling of WKT string literals (covered in other spatial tests) mixed with a column.

     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_Collect(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Collect(\'POINT(-5 -5)\', c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }

     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_COLLECT(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_COLLECT(\'POINT(-5 -5)\', g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DLengthTest.php (1)

26-31: DQL statement is consistent; consider adding a WKT literal case for broader input coverage

Current DQL using the ContainsGeometries fixture is consistent with suite patterns. Optionally, add a second case exercising a WKT literal to validate StringPrimary handling of string inputs (per prior learnings that WKT literals are accepted).

Apply this minimal diff to extend both arrays:

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_3DLength(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+            "SELECT ST_3DLength('LINESTRING Z (0 0 0, 1 1 1)') AS sclr_0 FROM ContainsGeometries c0_",
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_3DLENGTH(g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            "SELECT ST_3DLENGTH('LINESTRING Z (0 0 0, 1 1 1)') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g",
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineToCurveTest.php (1)

10-10: Optional: consider marking the test class final (if consistent across the suite).

Prevents accidental extension and mirrors common test-class practice.

-class ST_LineToCurveTest extends TestCase
+final class ST_LineToCurveTest extends TestCase
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php (2)

19-24: Add a literal-WKT case to exercise StringPrimary and recover some coverage

This test currently covers a column argument only. Adding a literal WKT case validates the StringPrimary mapping and may offset part of the reported coverage drop.

     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_Length(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Length(\'LINESTRING(0 0, 10 0)\') AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }

     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_LENGTH(g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_LENGTH(\'LINESTRING(0 0, 10 0)\') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }

Also applies to: 26-31


26-31: Confirm scope: single-arg variant only, or also geography two-arg form?

If you intend to support ST_Length(geography, boolean), consider adding a companion wrapper/test or extending coverage accordingly in this PR or a follow-up.

I can draft the additional wrapper/test skeleton if you want this included now.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TransformTest.php (1)

26-31: Support parameterized SRID in ST_Transform
Add InputParameter mapping so callers can use ST_TRANSFORM(g.geometry, :srid) instead of only literals:

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Transform.php
 protected function customizeFunction(): void
 {
     $this->addNodeMapping('StringPrimary');
     $this->addNodeMapping('Literal');
+    $this->addNodeMapping('InputParameter');
 }

Include a companion test case for a parameterized SRID.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2DTest.php (1)

19-31: Add a WKT-literal case to strengthen coverage and prove literal handling.

Per retrieved learnings, WKT string literals are accepted directly in spatial tests. Add a second DQL/SQL pair using a LINESTRING literal to cover both field and literal inputs and help offset the coverage drop.

Using the learnings noted above.

     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_Length2D(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Length2D(\'LINESTRING(0 0, 1 1)\') AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }

     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_LENGTH2D(g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_LENGTH2D(\'LINESTRING(0 0, 1 1)\') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ConvexHullTest.php (1)

26-31: DQL expectation is consistent; optional extra case to broaden coverage.

You could add a second pair using geometry2 to slightly expand coverage without changing patterns.

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_ConvexHull(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_ConvexHull(c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_CONVEXHULL(g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_CONVEXHULL(g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CollectionHomogenizeTest.php (2)

26-31: Add a literal-WKT case to broaden coverage (no DB semantics, just DQL→SQL)

Covers StringPrimary with a string literal, reinforcing the mapping and helping offset the coverage drop.

Apply these diffs:

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_CollectionHomogenize(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_CollectionHomogenize(\'GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,1 1))\') AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_COLLECTIONHOMOGENIZE(g.geometry1) FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsGeometries g',
+            'SELECT ST_COLLECTIONHOMOGENIZE(\'GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,1 1))\') FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsGeometries g',
         ];
     }

7-7: Consider allowing input parameters for flexibility

If you want ST_COLLECTIONHOMOGENIZE(:geom) to be usable in DQL, add InputParameter mapping in the production class.

Outside this file (production code) apply:

--- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CollectionHomogenize.php
+++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CollectionHomogenize.php
@@
     protected function customizeFunction(): void
     {
         $this->setFunctionPrototype('ST_CollectionHomogenize(%s)');
-        $this->addNodeMapping('StringPrimary');
+        $this->addNodeMapping('StringPrimary');
+        $this->addNodeMapping('InputParameter');
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AzimuthTest.php (1)

26-31: DQL statement is correct; consider a complementary integration test with WKT literals.

Optional: add an Integration test (mirroring StrictlyRightTest style) asserting translation when using WKT literals, e.g., SELECT ST_AZIMUTH('POINT(0 0)', 'POINT(1 1)') FROM … to cover literal arguments alongside entity fields.

<?php
declare(strict_types=1);

namespace Tests\Integration\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS;

final class ST_AzimuthTest extends TestCase
{
    protected function getExpectedSqlStatements(): array
    {
        return [
            "SELECT ST_Azimuth('POINT(0 0)', 'POINT(1 1)') AS sclr_0 FROM ContainsGeometries c0_",
        ];
    }

    protected function getDqlStatements(): array
    {
        return [
            "SELECT ST_AZIMUTH('POINT(0 0)', 'POINT(1 1)') FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsGeometries g",
        ];
    }
}
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AreaTest.php (1)

19-24: Consider adding a literal-WKT case to exercise StringPrimary parsing.
This keeps focus on DQL→SQL translation and bumps coverage slightly.

Apply this diff to add a second pair (keeps FROM for consistency with the harness):

     protected function getExpectedSqlStatements(): array
     {
         return [
-            'SELECT ST_Area(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Area(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Area(\'POLYGON((0 0,0 1,1 1,1 0,0 0))\') AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }

     protected function getDqlStatements(): array
     {
         return [
-            'SELECT ST_AREA(g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_AREA(g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_AREA(\'POLYGON((0 0,0 1,1 1,1 0,0 0))\') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }

Optional follow-up: If you plan to support the geography variant (ST_Area(geography[, boolean])), we can add a separate test covering the 2-arg form once the wrapper supports it.

Also applies to: 26-31

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php (1)

12-17: Consider allowing a parameterized max-vertices argument

If you’ll ever want ST_SUBDIVIDE(..., :maxVertices) in DQL, swap the second node mapping in the production wrapper from Literal to an arithmetic expression to accept params and expressions.

Suggested change in src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Subdivide.php:

 protected function customizeFunction(): void
 {
     $this->setFunctionPrototype('ST_Subdivide(%s, %s)');
     $this->addNodeMapping('StringPrimary');
-    $this->addNodeMapping('Literal');
+    $this->addNodeMapping('SimpleArithmeticExpression');
 }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnionTest.php (1)

26-31: Add a literal-WKT case for broader coverage (optional).
Per existing learnings, WKT literals are valid in these tests. Consider adding a second statement to cover a string literal argument.

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_UnaryUnion(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_UnaryUnion(\'POINT(-5 -5)\') AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_UNARYUNION(g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_UNARYUNION(\'POINT(-5 -5)\') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }

Also, if you plan to support an optional gridsize parameter in the wrapper, add a corresponding case here once implemented.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifferenceTest.php (1)

26-31: Optional: add reversed-argument case to guard against ordering regressions.

Adds a second pair to ensure arguments aren’t inadvertently swapped during translation.

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_SymDifference(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_SymDifference(c0_.geometry2, c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_SYMDIFFERENCE(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_SYMDIFFERENCE(g.geometry2, g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2DTest.php (2)

19-24: Optional: add a WKT-literal variant to exercise StringPrimary → geometry coercion

Adding a second case with a WKT literal as the first argument would cover the common pattern where PostGIS auto-coerces WKT strings to geometry.

Apply this diff to include an extra expected SQL statement:

         return [
             "SELECT ST_ClipByBox2D(c0_.geometry1, 'BOX(0 0, 10 10)') AS sclr_0 FROM ContainsGeometries c0_",
+            "SELECT ST_ClipByBox2D('POINT(0 0)', 'BOX(0 0, 10 10)') AS sclr_0 FROM ContainsGeometries c0_",
         ];

26-31: Pair the DQL with the literal-WKT variant for completeness

If you add the extra expected SQL, mirror it here to keep the arrays aligned.

         return [
             'SELECT ST_CLIPBYBOX2D(g.geometry1, \'BOX(0 0, 10 10)\') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_CLIPBYBOX2D(\'POINT(0 0)\', \'BOX(0 0, 10 10)\') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TranslateTest.php (2)

19-31: Add a test case for the 3D (dz) overload to broaden coverage.

PostGIS ST_Translate also accepts a 4th dz argument; adding it here will future-proof the wrapper and help offset the coverage drop.

Apply this diff to append a second case to both arrays:

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_Translate(c0_.geometry1, 1, 1) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Translate(c0_.geometry1, 1, 1, 1) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_TRANSLATE(g.geometry1, 1, 1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_TRANSLATE(g.geometry1, 1, 1, 1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }

Note: If the wrapper doesn’t yet accept a 4th argument, see the next comment to adjust its node mappings first.


7-7: Allow parameters/expressions for dx, dy (and dz if added).

Current wrapper maps offsets as Literal, which may be too restrictive for parameters or arithmetic. Consider using a numeric expression node type.

Outside this file (src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Translate.php), update customizeFunction() akin to:

protected function customizeFunction(): void
{
    // Support 2D and 3D forms and allow numeric expressions/parameters
    $this->setFunctionPrototype('ST_Translate(%s, %s, %s)');
    $this->addNodeMapping('StringPrimary');              // geometry
    $this->addNodeMapping('SimpleArithmeticExpression'); // dx
    $this->addNodeMapping('SimpleArithmeticExpression'); // dy

    // If your BaseFunction supports optional/variadic args:
    // $this->addOptionalNodeMapping('SimpleArithmeticExpression'); // dz
    // and switch prototype to 'ST_Translate(%s, %s, %s, %s)' when 4 args are present.
}
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SplitTest.php (2)

19-24: Optional: add a WKT literal case to exercise StringPrimary mapping.

This complements the column-vs-column case and aligns with prior spatial tests using WKT literals.

Apply this diff:

-        return [
-            'SELECT ST_Split(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
-        ];
+        return [
+            'SELECT ST_Split(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Split(c0_.geometry1, \'LINESTRING(0 0, 10 0)\') AS sclr_0 FROM ContainsGeometries c0_',
+        ];

26-31: Pair the DQL for the WKT literal case.

Keeps the 1:1 DQL↔SQL assertions consistent with the TestCase harness.

Apply this diff:

-        return [
-            'SELECT ST_SPLIT(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
-        ];
+        return [
+            'SELECT ST_SPLIT(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_SPLIT(g.geometry1, \'LINESTRING(0 0, 10 0)\') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+        ];
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistanceTest.php (1)

26-31: Optional: add a literal-WKT case to harden coverage.

Add a second pair using a 3D WKT literal for arg1; the project permits WKT strings in spatial function tests.

Apply:

     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_3DDistance(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_3DDistance(\'POINT Z(1 2 3)\', c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }

     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_3DDISTANCE(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_3DDISTANCE(\'POINT Z(1 2 3)\', g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistanceTest.php (1)

26-31: Add a WKT-literal case to exercise StringPrimary mapping and regain coverage.

Per prior patterns, WKT string literals are acceptable in spatial tests. Adding a second statement pair will increase coverage and validate literal handling.

Apply:

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
-            'SELECT ST_MaxDistance(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_MaxDistance(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+            // WKT literal as first argument
+            'SELECT ST_MaxDistance(\'POINT(0 0)\', c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
-            'SELECT ST_MAXDISTANCE(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_MAXDISTANCE(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            // WKT literal as first argument
+            'SELECT ST_MAXDISTANCE(\'POINT(0 0)\', g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RotateTest.php (2)

12-17: Correct DQL function mapping; consider covering the 3-arg ST_Rotate variant as well.
Current wrapper targets ST_Rotate(geom, angle). PostGIS also supports rotating around a point (geom, angle, point). If that variant is in scope for this PR, add a companion wrapper/test; otherwise, a follow-up PR is fine.

Example wrapper (new file) if you choose to add it:

<?php
declare(strict_types=1);

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

final class ST_Rotate3 extends BaseFunction
{
    protected function customizeFunction(): void
    {
        $this->setFunctionPrototype('ST_Rotate(%s, %s, %s)');
        $this->addNodeMapping('StringPrimary'); // geometry
        $this->addNodeMapping('Literal');       // angle in radians
        $this->addNodeMapping('StringPrimary'); // point (WKT or field)
    }
}

And a matching unit test could assert:

  • DQL: SELECT ST_ROTATE(g.geometry1, 0.785398, 'POINT(1 1)') FROM Fixtures...\ContainsGeometries g
  • SQL: SELECT ST_Rotate(c0_.geometry1, 0.785398, 'POINT(1 1)') AS sclr_0 FROM ContainsGeometries c0_

19-24: Support parameter binding in ST_Rotate
ST_Rotate currently only maps literal angles; dynamic angles via parameters will be rejected. In src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Rotate.php, after the existing addNodeMapping('Literal'), add addNodeMapping('InputParameter'). In tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RotateTest.php, add a test case using :angle to verify parameter binding.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnionTest.php (2)

12-17: Registration is correct; confirm 2-arg-only intent.

Mapping ST_UNION to ST_Union::class aligns with the wrapper. The current wrapper supports exactly two arguments; if aggregate ST_Union(geom)/ST_Union(geometry set) support is desired later, consider a separate wrapper or variadic mapping.


26-31: Add WKT-literal variant for ST_Union tests (optional)
Consider adding a DQL/SQL case using a raw WKT string (e.g. 'POINT(-5 -5)') to cover implicit casting; no existing PostGIS tests include direct literals—verify the exact SQL form in your suite before committing.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DistanceTest.php (2)

19-24: Optional: Add a case with a WKT literal to broaden coverage.
Covers column–literal usage, which the suite often exercises.

     protected function getExpectedSqlStatements(): array
     {
         return [
-            'SELECT ST_Distance(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Distance(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Distance(c0_.geometry1, \'POINT(0 0)\') AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }

26-31: Pair the WKT-literal SQL with matching DQL.
Keeps the arrays aligned index-wise in the base TestCase.

     protected function getDqlStatements(): array
     {
         return [
-            'SELECT ST_DISTANCE(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_DISTANCE(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_DISTANCE(g.geometry1, \'POINT(0 0)\') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CollectionExtractTest.php (1)

19-31: Optional: add a second case to widen coverage.

A second variant (different extract type) keeps the test fast and bumps coverage a bit.

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
-            'SELECT ST_CollectionExtract(c0_.geometry1, 1) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_CollectionExtract(c0_.geometry1, 1) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_CollectionExtract(c0_.geometry1, 3) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
-            'SELECT ST_COLLECTIONEXTRACT(g.geometry1, 1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_COLLECTIONEXTRACT(g.geometry1, 1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_COLLECTIONEXTRACT(g.geometry1, 3) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistanceTest.php (1)

26-31: DQL statement looks correct and aligns with fixture FQCN usage.
Optional: If you later add densifyFrac, consider a second DQL/SQL pair to cover it.

-        return [
-            'SELECT ST_HAUSDORFFDISTANCE(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
-        ];
+        return [
+            'SELECT ST_HAUSDORFFDISTANCE(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            // Uncomment once the wrapper supports the optional 3rd argument:
+            // 'SELECT ST_HAUSDORFFDISTANCE(g.geometry1, g.geometry2, 0.5) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+        ];
-        return [
-            'SELECT ST_HausdorffDistance(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
-        ];
+        return [
+            'SELECT ST_HausdorffDistance(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+            // And the matching SQL expectation:
+            // 'SELECT ST_HausdorffDistance(c0_.geometry1, c0_.geometry2, 0.5) AS sclr_0 FROM ContainsGeometries c0_',
+        ];
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ScaleTest.php (1)

19-31: Optional: allow bound parameters for scale factors (and consider 3D/origin variants)

If you want consumers to pass parameters (e.g., :sx, :sy), update the wrapper to accept arithmetic expressions instead of only literals, and add a companion test using parameters. Also consider covering the 3D/origin-anchored ST_Scale variants in follow-up tests.

Example wrapper tweak (outside this file, in src/.../ST_Scale.php):

protected function customizeFunction(): void
{
    $this->setFunctionPrototype('ST_Scale(%s, %s, %s)');
    $this->addNodeMapping('StringPrimary');               // geometry column/WKT
    $this->addNodeMapping('SimpleArithmeticExpression');  // x factor or :param
    $this->addNodeMapping('SimpleArithmeticExpression');  // y factor or :param
}
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php (1)

26-31: Optional: allow arithmetic expressions/parameters for distance and azimuth

Production mapping uses Literal for args 2 and 3, which prevents expressions (e.g., pi()/4) and bound parameters. If you want that flexibility, consider switching to SimpleArithmeticExpression for both args and add a second assertion that covers an arithmetic expression variant.

Proposed production change (outside this file):

 class ST_Project extends BaseFunction
 {
     protected function customizeFunction(): void
     {
         $this->setFunctionPrototype('ST_Project(%s, %s, %s)');
         $this->addNodeMapping('StringPrimary');
-        $this->addNodeMapping('Literal');
-        $this->addNodeMapping('Literal');
+        $this->addNodeMapping('SimpleArithmeticExpression');
+        $this->addNodeMapping('SimpleArithmeticExpression');
     }
 }

If you adopt the above, extend this test accordingly:

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
-            'SELECT ST_Project(c0_.geometry1, 1000, 0.785398) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Project(c0_.geometry1, 1000, 0.785398) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Project(c0_.geometry1, 500 + 500, pi() / 4) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
-            'SELECT ST_PROJECT(g.geometry1, 1000, 0.785398) FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsGeometries g',
+            'SELECT ST_PROJECT(g.geometry1, 1000, 0.785398) FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsGeometries g',
+            'SELECT ST_PROJECT(g.geometry1, 500 + 500, PI()/4) FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsGeometries g',
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php (1)

19-31: Add a decimal-radius case for broader coverage (still literal).

Include a second example with a decimal radius to ensure number formatting is preserved in DQL-to-SQL translation.

Apply this diff:

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
-            'SELECT ST_Buffer(c0_.geometry1, 10) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Buffer(c0_.geometry1, 10) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_Buffer(c0_.geometry1, 10.5) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
-            'SELECT ST_BUFFER(g.geometry1, 10) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_BUFFER(g.geometry1, 10) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_BUFFER(g.geometry1, 10.5) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyPreserveTopologyTest.php (1)

26-31: Add support for InputParameter and parameterized tolerance in ST_SimplifyPreserveTopology

  • In src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyPreserveTopology.php → customizeFunction(), add:
    $this->addNodeMapping('InputParameter');
  • In the corresponding unit test, extend both expected SQL and DQL arrays to include a parameterized variant:
    protected function getExpectedSqlStatements(): array
    {
        return [
            'SELECT ST_SimplifyPreserveTopology(c0_.geometry1, 0.5) AS sclr_0 FROM ContainsGeometries c0_',
  •     'SELECT ST_SimplifyPreserveTopology(c0_.geometry1, ?) AS sclr_0 FROM ContainsGeometries c0_',
    ];
    

    }

    protected function getDqlStatements(): array
    {
    return [
    'SELECT ST_SIMPLIFYPRESERVETOPOLOGY(g.geometry1, 0.5) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',

  •     'SELECT ST_SIMPLIFYPRESERVETOPOLOGY(g.geometry1, :t) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
    ];
    

    }

    
    
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force2DTest.php (1)

26-31: Consider adding a literal-WKT case for broader coverage

This validates StringPrimary handling of string literals (per existing guidance that WKT can be used directly). If you add it here, mirror it in expected SQL below.

Apply to DQL statements:

 return [
-    'SELECT ST_FORCE2D(g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+    'SELECT ST_FORCE2D(g.geometry1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+    'SELECT ST_FORCE2D(\'POINT(-5 -5)\') FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
 ];

And to expected SQL (in lines 19-24):

 return [
-    'SELECT ST_Force2D(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+    'SELECT ST_Force2D(c0_.geometry1) AS sclr_0 FROM ContainsGeometries c0_',
+    'SELECT ST_Force2D(\'POINT(-5 -5)\') AS sclr_0 FROM ContainsGeometries c0_',
 ];
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyTest.php (1)

19-31: Add parameterized tolerance test and InputParameter mapping in ST_Simplify

  • In tests/Unit/.../PostGIS/ST_SimplifyTest.php, add a second case for a DQL parameter:
         protected function getExpectedSqlStatements(): array
         {
             return [
                 'SELECT ST_Simplify(c0_.geometry1, 0.5) AS sclr_0 FROM ContainsGeometries c0_',
  •          'SELECT ST_Simplify(c0_.geometry1, ?) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
    
     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_SIMPLIFY(g.geometry1, 0.5) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
    
  •          'SELECT ST_SIMPLIFY(g.geometry1, :tolerance) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }
    
  • In src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Simplify.php, inside customizeFunction(), add:
        $this->addNodeMapping('InputParameter');
    to enable DQL parameter support.
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area2DTest.php (1)

19-24: Optional: add an integration test to catch invalid function names at runtime.

A minimal integration test executing SELECT ST_Area('POLYGON((0 0,1 0,1 1,0 1,0 0))') would prevent regressions like emitting non-existent functions.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php (2)

26-31: Add WKT-literal case to exercise StringPrimary mapping

Given both args are mapped as StringPrimary, add a variant with a WKT literal to ensure DQL→SQL translation covers that path.

 protected function getExpectedSqlStatements(): array
 {
     return [
         'SELECT ST_FrechetDistance(c0_.geometry1, c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
+        'SELECT ST_FrechetDistance(\'LINESTRING(0 0, 1 1)\', c0_.geometry2) AS sclr_0 FROM ContainsGeometries c0_',
     ];
 }

 protected function getDqlStatements(): array
 {
     return [
         'SELECT ST_FRECHETDISTANCE(g.geometry1, g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+        'SELECT ST_FRECHETDISTANCE(\'LINESTRING(0 0, 1 1)\', g.geometry2) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
     ];
 }

12-17: Extend wrapper to support optional densifyFrac
PostGIS ST_FrechetDistance has both two-arg and three-arg forms (with optional densifyFrac default –1 since 2.4.0) (postgis.net, postgis.net); your wrapper currently only supports two args. To enable the third parameter, update customizeFunction() to use

setFunctionPrototype('ST_FrechetDistance(%s, %s, %s)');
addNodeMapping('StringPrimary'); // third mapping

and add a test for the three-arg form.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyVWTest.php (2)

12-17: Register mapping looks right; consider allowing parameters in the wrapper.
To support DQL placeholders (e.g., :tolerance), extend the ST_SimplifyVW node mappings to include InputParameter.

Proposed wrapper tweak (outside this file):

--- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyVW.php
+++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyVW.php
@@
     protected function customizeFunction(): void
     {
-        $this->setFunctionPrototype('ST_SimplifyVW(%s, %s)');
-        $this->addNodeMapping('StringPrimary');
-        $this->addNodeMapping('Literal');
+        $this->setFunctionPrototype('ST_SimplifyVW(%s, %s)');
+        $this->addNodeMapping('StringPrimary'); // geometry column or WKT
+        $this->addNodeMapping('Literal');       // numeric tolerance / bool
+        $this->addNodeMapping('InputParameter'); // allow :params / ?1
     }

Optional test additions to cover placeholders:

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_SimplifyVW(c0_.geometry1, 0.5) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_SimplifyVW(c0_.geometry1, ?) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_SIMPLIFYVW(g.geometry1, 0.5) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_SIMPLIFYVW(g.geometry1, :tolerance) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }

19-31: Optional: add coverage for the 3-arg variant (preserveCollapsed).
PostGIS supports ST_SimplifyVW(geom, tolerance, preserveCollapsed boolean). If you target that version, add 3-arg support and tests.

Proposed deltas (wrapper + tests):

Wrapper (adds 3-arg prototype):

--- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyVW.php
+++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyVW.php
@@
-        $this->setFunctionPrototype('ST_SimplifyVW(%s, %s)');
+        $this->setFunctionPrototype('ST_SimplifyVW(%s, %s)');
+        $this->setFunctionPrototype('ST_SimplifyVW(%s, %s, %s)');

Tests:

@@
     protected function getExpectedSqlStatements(): array
     {
         return [
             'SELECT ST_SimplifyVW(c0_.geometry1, 0.5) AS sclr_0 FROM ContainsGeometries c0_',
+            'SELECT ST_SimplifyVW(c0_.geometry1, 0.5, true) AS sclr_0 FROM ContainsGeometries c0_',
         ];
     }
@@
     protected function getDqlStatements(): array
     {
         return [
             'SELECT ST_SIMPLIFYVW(g.geometry1, 0.5) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'SELECT ST_SIMPLIFYVW(g.geometry1, 0.5, true) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
         ];
     }

Comment on lines +7 to +17
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Buffer;
use Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase;

class ST_BufferTest extends TestCase
{
protected function getStringFunctions(): array
{
return [
'ST_BUFFER' => ST_Buffer::class,
];
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify parameter binding support for the radius argument.

Current wrapper maps the second arg as Literal. If bound parameters (e.g., :r) should be supported, ensure InputParameter (or equivalent) is allowed for arg2 in ST_Buffer. If not, consider adding a separate test asserting the parameterized form, or explicitly documenting that only literals are supported.

Run to confirm the wrapper’s node mappings:

If parameter binding is desired and currently unsupported, I can propose the minimal wrapper update and add a unit test variant that uses a bound parameter.


🏁 Script executed:

#!/bin/bash
# Inspect ST_Buffer mapping to see if InputParameter is supported for the radius.
rg -nC3 $'class ST_Buffer\b' src/
rg -nC2 $'setFunctionPrototype\\(\'ST_Buffer\\(%s, %s\\)\\\'' src/
rg -nC2 $'addNodeMapping\\(' src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Buffer.php

Length of output: 537


Add InputParameter mapping for radius argument
ST_Buffer currently only maps StringPrimary and Literal, so bound parameters (e.g. :r) aren’t supported. Add addNodeMapping('InputParameter') in src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Buffer.php and include a unit test in ST_BufferTest.php asserting a parameterized radius.

🤖 Prompt for AI Agents
In
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php
around lines 7 to 17 and
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Buffer.php, the
ST_Buffer function does not accept bound parameters for the radius because the
AST node mapping is missing; add addNodeMapping('InputParameter') to the node
mappings in ST_Buffer.php so InputParameter (e.g. :r) is recognized, and update
ST_BufferTest.php to include a unit test that uses a parameterized radius (bind
a value to :r and assert the generated SQL or parsing accepts the parameter) to
cover the new mapping.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Project.php (1)

25-31: Prototype and node mappings look correct (and parameters/expressions are supported).

Using SimpleArithmeticExpression for distance and azimuth enables bound params and arithmetic; good alignment with BaseFunction parsing.

🧹 Nitpick comments (5)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Project.php (1)

9-22: Docblock: clarify geometry vs. geography semantics.

PostGIS treats distance/azimuth differently for geography (geodesic, meters) vs geometry (planar, SRID units). A short note avoids confusion.

  /**
   * Implementation of PostGIS ST_Project() function.
   *
- * Projects a point along a geodesic.
- * Useful for calculating positions along great circle paths.
+ * Projects a point by distance and azimuth.
+ * Note: On geography this is geodesic (meters); on geometry it is planar in SRID units.
   *
   * @see https://postgis.net/docs/ST_Project.html
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php (1)

19-33: Add a WKT literal case to exercise StringPrimary input.

Covers the common pattern of passing a WKT point directly (per existing spatial tests).

     protected function getExpectedSqlStatements(): array
     {
         return [
             'projects with literal values' => 'SELECT ST_Project(c0_.geometry1, 1000, 0.785398) AS sclr_0 FROM ContainsGeometries c0_',
             'projects with arithmetic expressions' => 'SELECT ST_Project(c0_.geometry1, 1000 * 2, 0.785398 + 0.1) AS sclr_0 FROM ContainsGeometries c0_',
+            'projects with WKT literal' => "SELECT ST_Project('POINT(-5 -5)', 1000, 0.0) AS sclr_0 FROM ContainsGeometries c0_",
         ];
     }
 
     protected function getDqlStatements(): array
     {
         return [
             'projects with literal values' => 'SELECT ST_PROJECT(g.geometry1, 1000, 0.785398) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
             'projects with arithmetic expressions' => 'SELECT ST_PROJECT(g.geometry1, 1000 * 2, 0.785398 + 0.1) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g',
+            'projects with WKT literal' => "SELECT ST_PROJECT('POINT(-5 -5)', 1000, 0.0) FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g",
         ];
     }
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)

94-99: Standardize SRID for the new row to avoid mixed-SRID surprises.

The newly added geometry values are plain WKT while earlier rows use SRID=4326; mixing unknown SRID (0) with 4326 can cause function errors or inconsistent behavior. Prefer making these EWKT too.

-                'geometry1' => 'LINESTRING(0 0, 4 4)',
-                'geometry2' => 'POINT(2 2)',
+                'geometry1' => 'SRID=4326;LINESTRING(0 0, 4 4)',
+                'geometry2' => 'SRID=4326;POINT(2 2)',
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineCrossingDirectionTest.php (1)

82-82: Avoid tying assertion to fixture row count; predicate here is constant.

The WHERE uses only literals, so every row matches and the count equals table size. This is brittle when fixtures change. Either reference g.geometry1/g.geometry2 in the predicate or relax the assertion.

Minimal change:

-        $this->assertCount(9, $result);
+        $this->assertGreaterThan(0, \count($result));

Alternative (data-dependent predicate example):

WHERE ST_LINECROSSINGDIRECTION(g.geometry1, 'LINESTRING(0 2, 2 0)') = 1
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RelateMatchTest.php (1)

73-73: Exact count depends on fixtures; make the filter stable or relax the check.

assertCount(1, ...) is correct today but will break if another row matches the pattern. Pin to a specific id in the DQL or use a non-brittle assertion.

Option A (pin result set to a known row and keep assertCount(1)):

-        $dql = 'SELECT g.id, ST_RELATEMATCH(ST_RELATE(g.geometry1, g.geometry2), \'FF0FFF0F2\') as matches_disjoint_points
-                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
-                WHERE ST_RELATEMATCH(ST_RELATE(g.geometry1, g.geometry2), \'FF0FFF0F2\') = TRUE';
+        $dql = 'SELECT g.id, ST_RELATEMATCH(ST_RELATE(g.geometry1, g.geometry2), \'FF0FFF0F2\') as matches_disjoint_points
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
+                WHERE ST_RELATEMATCH(ST_RELATE(g.geometry1, g.geometry2), \'FF0FFF0F2\') = TRUE AND g.id = 1';

Option B (relax assertion):

-        $this->assertCount(1, $result);
+        $this->assertGreaterThan(0, \count($result));
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 16258ad and 9cfe5f3.

📒 Files selected for processing (7)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2D.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Project.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineCrossingDirectionTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RelateMatchTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (2 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2DTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2D.php
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2DTest.php
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#352
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpInstrTest.php:1-67
Timestamp: 2025-04-20T11:24:18.300Z
Learning: This PostgreSQL-for-Doctrine project is a translation layer only, focusing on correctly converting Doctrine DQL to PostgreSQL SQL syntax. It ensures arguments are passed in the expected format but does not test or handle PostgreSQL's actual function behavior or data handling. Test cases should focus on DQL-to-SQL translation and argument validation, not on PostgreSQL-specific behaviors.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RelateMatchTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineCrossingDirectionTest.php
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Project.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineCrossingDirectionTest.php
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineCrossingDirectionTest.php
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineCrossingDirectionTest.php
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
📚 Learning: 2025-04-22T00:03:37.733Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.

Applied to files:

  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
📚 Learning: 2025-04-20T11:24:18.300Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#352
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpInstrTest.php:1-67
Timestamp: 2025-04-20T11:24:18.300Z
Learning: This PostgreSQL-for-Doctrine project is a translation layer only, focusing on correctly converting Doctrine DQL to PostgreSQL SQL syntax. It ensures arguments are passed in the expected format but does not test or handle PostgreSQL's actual function behavior or data handling. Test cases should focus on DQL-to-SQL translation and argument validation, not on PostgreSQL-specific behaviors.

Applied to files:

  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
📚 Learning: 2025-08-27T18:19:35.789Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.

Applied to files:

  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Project.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
📚 Learning: 2025-04-11T11:23:44.192Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#340
File: tests/MartinGeorgiev/Doctrine/DBAL/Types/InetArrayTest.php:145-145
Timestamp: 2025-04-11T11:23:44.192Z
Learning: In the PostgreSQL for Doctrine test cases, methods that test database-to-PHP conversions should use `mixed` type for parameter and include non-string test cases in their data providers, following the pattern in classes like InetTest, CidrTest, and MacaddrTest.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
🧬 Code graph analysis (2)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php (1)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Project.php (1)
  • ST_Project (23-32)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Project.php (1)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseFunction.php (3)
  • BaseFunction (20-105)
  • setFunctionPrototype (57-60)
  • addNodeMapping (62-65)
🔇 Additional comments (1)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php (1)

12-17: Registration of ST_PROJECT alias looks good.

Matches project conventions for string functions in tests.

Comment on lines +47 to 49
'geometry1' => 'SRID=4326;POINT(0 0)',
'geometry2' => 'SRID=4326;POINT(1 1)',
'geography1' => 'SRID=4326;POINT(-9.1393 38.7223)',
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

EWKT strings with ST_GeomFromText will fail — switch to ST_GeomFromEWKT for geometry inserts.

You changed several geometry literals to EWKT (SRID=4326;...), but the insert still uses ST_GeomFromText(?). PostGIS doesn’t parse SRID-prefixed EWKT via ST_GeomFromText; this will error at insert time. Use ST_GeomFromEWKT for geometry1/geometry2 (geography calls can stay as-is).

Apply this diff:

-                VALUES (ST_GeomFromText(?), ST_GeomFromText(?), ST_GeogFromText(?), ST_GeogFromText(?))
+                VALUES (ST_GeomFromEWKT(?), ST_GeomFromEWKT(?), ST_GeogFromText(?), ST_GeogFromText(?))

Also applies to: 53-55, 59-61, 102-106

🤖 Prompt for AI Agents
In
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
around lines 47-49 (and also apply same change at 53-55, 59-61, and 102-106),
the test inserts use EWKT strings like 'SRID=4326;POINT(...)' but still call
ST_GeomFromText, which will fail; update the inserts that create geometry values
(geometry1, geometry2, etc.) to use ST_GeomFromEWKT instead of ST_GeomFromText,
leaving geography calls as-is so EWKT SRID-prefixed literals are parsed
correctly.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (14)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AreaTest.php (2)

26-28: Use a delta for float equality to avoid brittle comparisons

Exact float equality can flake across GEOS/PostGIS builds. Suggest tolerating a tiny epsilon.

Apply:

-        $this->assertEquals(16, $result[0]['result']);
+        $this->assertEqualsWithDelta(16.0, $result[0]['result'], 1e-12);

10-17: Optional: add a geography variant to exercise the same mapping

Verifies the wrapper also works when targeting GEOGRAPHY columns; assertion stays robust across versions.

Apply near the end of the class (before the closing brace):

@@
     public function returns_zero_for_point(): void
     {
         $dql = 'SELECT ST_AREA(g.geometry1) as result
                 FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
                 WHERE g.id = 1';

         $result = $this->executeDqlQuery($dql);
         $this->assertEquals(0, $result[0]['result']);
     }
+
+    #[Test]
+    public function returns_positive_area_for_geography_polygon(): void
+    {
+        $dql = 'SELECT ST_AREA(g.geography1) as result
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
+                WHERE g.id = 2';
+
+        $result = $this->executeDqlQuery($dql);
+        $this->assertGreaterThan(0.0, $result[0]['result']);
+    }
 }
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php (2)

26-28: Relax the numeric tolerance for portability

1e-16 can be too strict across platforms/versions; 1e-12 is typically safe while still exacting.

Apply:

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.0000000000000001, 'Length of LINESTRING(0 0, 1 1, 2 2) = √2 + √2 = 2√2');
+        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 1e-12, 'Length of LINESTRING(0 0, 1 1, 2 2) = √2 + √2 = 2√2');

37-39: Use delta for polygon perimeter as well

Keeps float assertions consistent and resilient.

Apply:

-        $this->assertEquals(16, $result[0]['result']);
+        $this->assertEqualsWithDelta(16.0, $result[0]['result'], 1e-12);
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php (3)

12-12: Relax numeric tolerance and centralize it to avoid flaky tests across GEOS/PostGIS versions

The current delta (1e-16) is extremely tight for DB-side floating-point ops and may fail across platforms/library versions. Recommend a shared tolerance (e.g., 1e-9).

Apply:

 class ST_BufferTest extends SpatialOperatorTestCase
 {
+    private const DELTA = 1e-9;
+
     protected function getStringFunctions(): array
     {
         return [
             'ST_AREA' => ST_Area::class,
             'ST_BUFFER' => ST_Buffer::class,
         ];
     }
@@
-        $this->assertEqualsWithDelta(3.121445152258052, $result[0]['result'], 0.0000000000000001, 'Buffer of radius 1 around a point shall create a polygon approximation of a circle');
+        $this->assertEqualsWithDelta(3.121445152258052, $result[0]['result'], self::DELTA, 'Buffer of radius 1 around a point shall create a polygon approximation of a circle');
@@
-        $this->assertEqualsWithDelta(24.780361288064512, $result[0]['result'], 0.0000000000000001, 'Buffer of 0.5 around 4x4 polygon increases area from 16 to approximately 24.78');
+        $this->assertEqualsWithDelta(24.780361288064512, $result[0]['result'], self::DELTA, 'Buffer of 0.5 around 4x4 polygon increases area from 16 to approximately 24.78');
@@
-        $this->assertEqualsWithDelta(1.2562286559887985, $result[0]['result'], 0.0000000000000001, 'Buffer of 0.2 around LINESTRING(0 0, 1 1, 2 2) creates a polygon with specific area');
+        $this->assertEqualsWithDelta(1.2562286559887985, $result[0]['result'], self::DELTA, 'Buffer of 0.2 around LINESTRING(0 0, 1 1, 2 2) creates a polygon with specific area');

Also applies to: 28-30, 39-41, 50-52


24-26: Optional: make tests deterministic by specifying quad_segs explicitly

These expectations match PostGIS’s default quad_segs=8 (32-gon). To future-proof, consider accepting the 3rd style arg in ST_Buffer (e.g., 'quad_segs=8') and using it in tests to lock behavior.

Example DQL (after enabling a 3rd arg in the wrapper):

  • ST_BUFFER(g.geometry1, 1, 'quad_segs=8')
  • ST_BUFFER(g.geometry1, 0.5, 'quad_segs=8')
  • ST_BUFFER(g.geometry1, 0.2, 'quad_segs=8')

If you want, I can draft the wrapper update for the 3rd argument and adjust these tests accordingly.

Also applies to: 35-37, 46-48


21-23: Nit: clarify test names

Rename to reflect that the assertions verify the area of the buffered geometry.

-    public function returns_buffered_point(): void
+    public function returns_area_of_buffered_point(): void
@@
-    public function returns_buffered_polygon(): void
+    public function returns_area_of_buffered_polygon(): void
@@
-    public function returns_buffered_linestring(): void
+    public function returns_area_of_buffered_linestring(): void

Also applies to: 33-35, 44-46

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistanceTest.php (3)

19-28: Loosen numeric tolerance and avoid magic number.

1e-16 is overly tight and can be flaky across platforms/PG/PostGIS builds. Also prefer expressing √2 directly.

Apply:

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 0.0000000000000001, 'Maximum distance between POINT(0 0) and POINT(1 1) = √2');
+        $result = $this->executeDqlQuery($dql);
+        $this->assertCount(1, $result);
+        $this->assertEqualsWithDelta(\sqrt(2.0), (float) $result[0]['result'], 1e-12, 'Maximum distance between POINT(0 0) and POINT(1 1) = √2');

30-39: Use delta assertion for zero as well.

Even identical geometries may yield tiny FP noise; assert with a small delta and also check row count.

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEquals(0, $result[0]['result']);
+        $result = $this->executeDqlQuery($dql);
+        $this->assertCount(1, $result);
+        $this->assertEqualsWithDelta(0.0, (float) $result[0]['result'], 1e-15);

41-50: Same tolerance concern; derive √18 programmatically.

Express the expectation as √18 and relax tolerance; also assert single-row result.

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEqualsWithDelta(4.242640687119285, $result[0]['result'], 0.0000000000000001, 'Maximum distance between polygon corners (0,0) to (3,3) = √18');
+        $result = $this->executeDqlQuery($dql);
+        $this->assertCount(1, $result);
+        $this->assertEqualsWithDelta(\sqrt(18.0), (float) $result[0]['result'], 1e-12, 'Maximum distance between polygon corners (0,0) to (3,3) = √18');
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DistanceTest.php (4)

22-28: Relax tolerance and avoid magic number for √2

The 1e-16 tolerance is brittle across PG/GEOS builds. Also replace the hardcoded 1.4142… with a computed value.

Apply:

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 0.0000000000000001, 'Distance between POINT(0 0) and POINT(1 1) = √2');
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(\hypot(1, 1), (float) $result[0]['result'], 1e-12, 'Distance between POINT(0 0) and POINT(1 1) = √2');

33-39: Use delta-based assertion for zero distance

Guard against tiny negative/positive epsilons and driver string casting.

Apply:

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEquals(0, $result[0]['result']);
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(0.0, (float) $result[0]['result'], 1e-12);

44-50: Same for overlapping polygons

Mirror the delta-based assertion to avoid flakiness.

Apply:

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEquals(0, $result[0]['result']);
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(0.0, (float) $result[0]['result'], 1e-12);

41-50: Add coverage for geography and touch/intersection edge cases

Optional but useful: a geography variant (meters) and “touching boundary”/“point on line” cases already present in fixtures (ids 7 and 8).

You could append:

#[Test]
public function returns_geography_distance_in_meters_within_reasonable_range(): void
{
    $dql = 'SELECT ST_DISTANCE(g.geography1, g.geography2) as result
            FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
            WHERE g.id = 1';

    $result = $this->executeDqlQuery($dql);
    $meters = (float) $result[0]['result'];
    $this->assertGreaterThan(1_500_000, $meters);
    $this->assertLessThan(1_700_000, $meters);
}

#[Test]
public function returns_zero_for_touching_polygons(): void
{
    $dql = 'SELECT ST_DISTANCE(g.geometry1, g.geometry2) as result
            FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
            WHERE g.id = 7';

    $result = $this->executeDqlQuery($dql);
    $this->assertEqualsWithDelta(0.0, (float) $result[0]['result'], 1e-12);
}

#[Test]
public function returns_zero_for_point_on_linestring(): void
{
    $dql = 'SELECT ST_DISTANCE(g.geometry1, g.geometry2) as result
            FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
            WHERE g.id = 8';

    $result = $this->executeDqlQuery($dql);
    $this->assertEqualsWithDelta(0.0, (float) $result[0]['result'], 1e-12);
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9cfe5f3 and 3805780.

📒 Files selected for processing (6)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AreaTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DistanceTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistanceTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/StrictlyBelowTest.php (0 hunks)
💤 Files with no reviewable changes (1)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/StrictlyBelowTest.php
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#0
File: :0-0
Timestamp: 2025-08-24T16:52:32.488Z
Learning: All new features in this repository must include proper test coverage before approval - this ltree implementation demonstrates exemplary test coverage with comprehensive unit tests, integration tests, data providers for edge cases, and validation of all relationships and error conditions.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#0
File: :0-0
Timestamp: 2025-08-25T21:35:48.228Z
Learning: Extensions in integration tests should be created in the createTestSchema() method of the base TestCase, following the established PostGIS pattern with proper error handling, not in individual test createXExtension() methods.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AreaTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AreaTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AreaTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AreaTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php
📚 Learning: 2025-08-27T18:19:35.789Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AreaTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php
🧬 Code graph analysis (5)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DistanceTest.php (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Distance.php (1)
  • ST_Distance (23-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-116)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistanceTest.php (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistance.php (1)
  • ST_MaxDistance (23-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-116)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php (5)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Buffer.php (1)
  • ST_Buffer (23-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AreaTest.php (4)
  • Test (19-28)
  • Test (30-39)
  • Test (41-50)
  • getStringFunctions (12-17)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-116)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AreaTest.php (4)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php (4)
  • Test (21-30)
  • Test (32-41)
  • Test (43-52)
  • getStringFunctions (13-19)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-116)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: Code Quality
  • GitHub Check: PHP 8.4 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM 3.0 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.3 + Doctrine ORM latest + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.18 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.1 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.3
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.1
  • GitHub Check: wait-for-tests-worflows-before-upload
🔇 Additional comments (9)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AreaTest.php (3)

12-17: LGTM: correct DQL function mapping

Maps ST_AREA to ST_Area::class as expected.


33-39: LGTM: area of a linestring is zero

Assertion is correct and stable.


41-50: LGTM: area of a point is zero

Assertion is correct and stable.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php (2)

12-17: LGTM: correct DQL function mapping

Maps ST_LENGTH to ST_Length::class as expected.


48-50: LGTM: point has zero length

Assertion is correct and stable.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BufferTest.php (1)

13-19: LGTM: Function registration for ST_AREA and ST_BUFFER is correct

Mappings align with the wrappers and established integration-test patterns.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_MaxDistanceTest.php (1)

12-17: Function alias mapping looks correct.

'ST_MAXDISTANCE' => ST_MaxDistance::class matches the DQL used below and the wrapper’s prototype.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DistanceTest.php (2)

12-17: ST_DISTANCE function registered correctly

Mapping uses the established uppercase key and the correct class. Looks consistent with the suite.


10-17: No unit-level SQL mapping test needed for ST_Distance
A unit test already exists at tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DistanceTest.php that asserts the generated SQL (ST_Distance(p1, p2)) for the AST translation.

Comment on lines +19 to +27
#[Test]
public function returns_distance_between_points(): void
{
$dql = 'SELECT ST_DISTANCE(g.geometry1, g.geometry2) as result
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
WHERE g.id = 1';

$result = $this->executeDqlQuery($dql);
$this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 0.0000000000000001, 'Distance between POINT(0 0) and POINT(1 1) = √2');
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Fixture ingestion uses EWKT: double-check loader functions

This test assumes SRID is preserved in fixtures. If SpatialOperatorTestCase inserts EWKT via ST_GeomFromText(...), switch to ST_GeomFromEWKT(...) to avoid silently dropping SRID.

Run:

Expected: ST_GeomFromEWKT for geometry, ST_GeogFromText for geography. If it’s ST_GeomFromText with 'SRID=…;', update the loader accordingly.


🏁 Script executed:

#!/bin/bash
# Verify EWKT usage in the spatial fixture loader
fd SpatialOperatorTestCase.php
path="$(fd -a SpatialOperatorTestCase.php | head -n1)"
rg -nP -C2 'ST_GeomFrom(EWKT|Text)\(' "$path"
rg -nP -C2 'SRID=4326;' "$path"

Length of output: 4549


Use EWKT functions in SpatialOperatorTestCase fixtures to preserve SRID

In tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php, update the INSERT to use EWKT-aware constructors:

- VALUES (ST_GeomFromText(?), ST_GeomFromText(?), ST_GeogFromText(?), ST_GeogFromText(?))
+ VALUES (ST_GeomFromEWKT(?),    ST_GeomFromEWKT(?),    ST_GeogFromEWKT(?),    ST_GeogFromEWKT(?))
📝 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
#[Test]
public function returns_distance_between_points(): void
{
$dql = 'SELECT ST_DISTANCE(g.geometry1, g.geometry2) as result
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
WHERE g.id = 1';
$result = $this->executeDqlQuery($dql);
$this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 0.0000000000000001, 'Distance between POINT(0 0) and POINT(1 1) = √2');
// In tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
// …inside the fixture setup, update the INSERT’s VALUES clause:
- VALUES (
- ST_GeomFromText(?),
- ST_GeomFromText(?),
- ST_GeogFromText(?),
- ST_GeogFromText(?)
VALUES (
ST_GeomFromEWKT(?),
ST_GeomFromEWKT(?),
ST_GeogFromEWKT(?),
ST_GeogFromEWKT(?)
)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)

108-110: EWKT strings require ST_GeomFromEWKT — current INSERTs will fail.

You pass SRID=…;WKT for geometry1/2 but still call ST_GeomFromText, which can’t parse EWKT.

-                VALUES (ST_GeomFromText(?), ST_GeomFromText(?), ST_GeogFromText(?), ST_GeogFromText(?))
+                VALUES (ST_GeomFromEWKT(?), ST_GeomFromEWKT(?), ST_GeogFromText(?), ST_GeogFromText(?))
#!/bin/bash
# Ensure no remaining EWKT passed to ST_GeomFromText
rg -nP "ST_GeomFromText\\(" -C2 tests/Integration | sed -n '1,200p'
🧹 Nitpick comments (8)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_PerimeterTest.php (2)

26-28: Use delta-based assertions to avoid float flakiness across PostGIS versions.

Perimeter returns double precision; comparing as ints can be brittle.

-        $this->assertEquals(16, $result[0]['result']);
+        $this->assertEqualsWithDelta(16.0, $result[0]['result'], 1e-9);

-        $this->assertEquals(8, $result[0]['result']);
+        $this->assertEqualsWithDelta(8.0, $result[0]['result'], 1e-9);

-        $this->assertEquals(8, $result[0]['result']);
+        $this->assertEqualsWithDelta(8.0, $result[0]['result'], 1e-9);

Also applies to: 37-39, 70-71


52-61: Message is helpful; consider asserting with delta here too.

Zero is fine, but using a tiny delta keeps consistency with other numeric assertions.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistanceTest.php (1)

26-28: Relax tolerance to avoid precision-related flakes.

1e-16 is too strict across platforms/PostGIS builds; 1e-12 is safer.

-        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 0.0000000000000001);
+        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 1e-12);

-        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 0.0000000000000001);
+        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 1e-12);

Also applies to: 48-50

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AzimuthTest.php (1)

27-27: Prefer computed constants (pi()) over hard-coded literals and legacy M_PI

Reduces magic numbers and avoids potential deprecations for M_PI in newer PHP versions.

-        $this->assertEqualsWithDelta(0.7853981633974483, $result[0]['result'], 0.0000000000000001);
+        $this->assertEqualsWithDelta(pi() / 4, $result[0]['result'], 1.0e-16);
-        $this->assertLessThan(2 * M_PI, $result[0]['result']);
+        $this->assertLessThan(2 * pi(), $result[0]['result']);
-        $this->assertEqualsWithDelta(3.9269908169872423, $result[0]['result'], 0.0000000000000001);
+        $this->assertEqualsWithDelta(5 * pi() / 4, $result[0]['result'], 1.0e-16);

Also applies to: 50-50, 61-61

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php (4)

26-28: Replace magic number with expression for clarity

Compute the expected length instead of using a long literal.

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.0000000000000001, 'Length of LINESTRING(0 0, 1 1, 2 2) = √2 + √2 = 2√2');
+        $this->assertEqualsWithDelta(2 * sqrt(2), $result[0]['result'], 1.0e-16, 'Length of LINESTRING(0 0, 1 1, 2 2) = √2 + √2 = 2√2');

37-39: Tighten the assertion message (ST_Length on polygons is 0 regardless of CRS)

ST_Length returns 0 for areal geometries; perimeter is given by ST_Perimeter. Adjust message to avoid implying CRS dependence.

-        $this->assertEquals(0, $result[0]['result'], 'PostGIS behavior expects length of 0 for polygons in geographic coordinate systems');
+        $this->assertEquals(0, $result[0]['result'], 'ST_Length returns 0 for polygon geometries; use ST_Perimeter for perimeter (CRS-agnostic).');

59-61: Consider tolerance for numeric comparison

Even in projected CRS, DB drivers may return floats; a tiny delta makes the test more robust.

-        $this->assertEquals(2000, $result[0]['result']);
+        $this->assertEqualsWithDelta(2000, $result[0]['result'], 1.0e-12);

70-72: Clarify assertion message for polygons

Reword to explicitly reference ST_Perimeter for polygons.

-        $this->assertEquals(0, $result[0]['result'], 'PostGIS design mandates that ST_Length is for linear geometries only, so this is not expected to compute a length');
+        $this->assertEquals(0, $result[0]['result'], 'ST_Length applies to linear geometries; polygons yield 0. Use ST_Perimeter to measure polygon boundary length.');
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3805780 and f4aa12a.

📒 Files selected for processing (5)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistanceTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AzimuthTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_PerimeterTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (3 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#352
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpInstrTest.php:1-67
Timestamp: 2025-04-20T11:24:18.300Z
Learning: This PostgreSQL-for-Doctrine project is a translation layer only, focusing on correctly converting Doctrine DQL to PostgreSQL SQL syntax. It ensures arguments are passed in the expected format but does not test or handle PostgreSQL's actual function behavior or data handling. Test cases should focus on DQL-to-SQL translation and argument validation, not on PostgreSQL-specific behaviors.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AzimuthTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_PerimeterTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AzimuthTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_PerimeterTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AzimuthTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_PerimeterTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php
📚 Learning: 2025-08-27T18:19:35.789Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AzimuthTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_PerimeterTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AzimuthTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_PerimeterTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php
📚 Learning: 2025-08-19T13:07:15.184Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#421
File: docs/AVAILABLE-TYPES.md:31-33
Timestamp: 2025-08-19T13:07:15.184Z
Learning: In martin-georgiev/postgresql-for-doctrine, the point[] array type should be documented as "point[]" not "_point" in the AVAILABLE-TYPES.md table, to be consistent with all other array types like text[], jsonb[], inet[], etc.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
📚 Learning: 2025-08-25T21:35:48.228Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#0
File: :0-0
Timestamp: 2025-08-25T21:35:48.228Z
Learning: Extensions in integration tests should be created in the createTestSchema() method of the base TestCase, following the established PostGIS pattern with proper error handling, not in individual test createXExtension() methods.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php
🧬 Code graph analysis (5)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistanceTest.php (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistance.php (1)
  • ST_3DDistance (23-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AzimuthTest.php (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Azimuth.php (1)
  • ST_Azimuth (23-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_PerimeterTest.php (4)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Perimeter.php (1)
  • ST_Perimeter (23-30)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistanceTest.php (3)
  • Test (19-28)
  • Test (30-39)
  • Test (41-50)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AzimuthTest.php (4)
  • Test (19-28)
  • Test (30-39)
  • Test (41-51)
  • Test (53-62)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php (5)
  • Test (19-28)
  • Test (30-39)
  • Test (41-50)
  • Test (52-61)
  • Test (63-72)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • dropTestTableIfItExists (239-246)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.14 + Doctrine Lexer 1.2
  • GitHub Check: PHP 8.4 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.4 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.3 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM latest + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.18 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.1 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: wait-for-tests-worflows-before-upload
🔇 Additional comments (6)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_PerimeterTest.php (1)

12-17: DQL function mapping looks correct.

Mapping ST_PERIMETER to the wrapper is consistent with the project’s pattern.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)

11-11: Nice: single TABLE_NAME constant.

Reduces duplication across tests.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DDistanceTest.php (2)

12-17: DQL function mapping is spot on.


30-39: Polygons case reads well.

Zero distance for overlapping polygons is a good sanity check.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_AzimuthTest.php (1)

12-17: LGTM: correct function registration

ST_AZIMUTH is mapped to the expected wrapper and follows the project’s pattern. Namespaces align with existing tests (per fixtures pattern).

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LengthTest.php (1)

12-17: LGTM: correct function registration

ST_LENGTH is wired to the expected wrapper; consistent with existing integration tests.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistanceTest.php (3)

22-28: Loosen delta and derive expected via sqrt() to avoid flakiness.

Double precision and GEOS/PostGIS versions can vary slightly; an absolute delta of 1e-16 is too tight.

Apply:

-        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 0.0000000000000001);
+        $this->assertEqualsWithDelta(\sqrt(2.0), (float) $result[0]['result'], 1.0E-12);

33-39: Use delta-based assertion for zero as well.

Guard against subnormal rounding; stay consistent with other float checks.

-        $this->assertEquals(0, $result[0]['result']);
+        $this->assertEqualsWithDelta(0.0, (float) $result[0]['result'], 1.0E-12);

44-50: Same tolerance improvement for polygons.

Use sqrt() and a slightly looser delta.

-        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 0.0000000000000001);
+        $this->assertEqualsWithDelta(\sqrt(2.0), (float) $result[0]['result'], 1.0E-12);

Optionally, add a symmetry check (arguments swapped) to document the metric’s property:

#[Test]
public function returns_same_distance_when_arguments_swapped(): void
{
    $dql = 'SELECT ST_HAUSDORFFDISTANCE(g.geometry2, g.geometry1) as result
            FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
            WHERE g.id = 2';

    $result = $this->executeDqlQuery($dql);
    $this->assertEqualsWithDelta(\sqrt(2.0), (float) $result[0]['result'], 1.0E-12);
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f4aa12a and 13ee267.

📒 Files selected for processing (1)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistanceTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#0
File: :0-0
Timestamp: 2025-08-24T16:52:32.488Z
Learning: All new features in this repository must include proper test coverage before approval - this ltree implementation demonstrates exemplary test coverage with comprehensive unit tests, integration tests, data providers for edge cases, and validation of all relationships and error conditions.
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistanceTest.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistanceTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistanceTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistanceTest.php
📚 Learning: 2025-08-27T18:19:35.789Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistanceTest.php
🧬 Code graph analysis (1)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistanceTest.php (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistance.php (1)
  • ST_HausdorffDistance (23-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: PHP 8.4 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM 3.0 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM latest + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.3 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.1 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.1 + Doctrine ORM latest + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.1 + Doctrine ORM 3.0 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.1 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: wait-for-tests-worflows-before-upload
🔇 Additional comments (1)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_HausdorffDistanceTest.php (1)

12-17: Function registration mapping looks correct.

The DQL function name and class mapping align with existing patterns and should register cleanly.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DPerimeterTest.php (2)

22-28: Use float assertions with tolerance to avoid brittle tests.

ST_3DPERIMETER returns a floating-point; compare with a delta and cast the result to float to avoid string/float mismatches from DB drivers.

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEquals(16, $result[0]['result']);
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(16.0, (float) $result[0]['result'], 1e-9);

33-39: Same here: prefer tolerant float assertion.

Zero is usually safe, but keep consistency and guard against formatting/type issues.

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEquals(0, $result[0]['result']);
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(0.0, (float) $result[0]['result'], 1e-12);
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_EnvelopeTest.php (3)

37-43: Numeric comparisons: consider a tiny delta for future-proofing

PostGIS returns exact values here, but guarding against FP drift keeps tests stable across PG/PostGIS versions.

-        $this->assertEquals(16, $result[0]['result'], 'Envelope of POLYGON((0 0, 0 4, 4 4, 4 0, 0 0)) should have area = 16');
+        $this->assertEqualsWithDelta(16.0, (float) $result[0]['result'], 1.0E-12, 'Envelope of POLYGON((0 0, 0 4, 4 4, 4 0, 0 0)) should have area = 16');

48-54: Same here: use delta for area assertion

Keeps the test robust if driver casts vary or PostGIS introduces minor numeric differences.

-        $this->assertEquals(4, $result[0]['result'], 'Envelope of LINESTRING(0 0, 1 1, 2 2) should be POLYGON((0 0, 0 2, 2 2, 2 0, 0 0)) with area = 4');
+        $this->assertEqualsWithDelta(4.0, (float) $result[0]['result'], 1.0E-12, 'Envelope of LINESTRING(0 0, 1 1, 2 2) should be POLYGON((0 0, 0 2, 2 2, 2 0, 0 0)) with area = 4');

12-21: Optional: add a quick WKT literal case to validate implicit casting

Integration suite often uses fixtures, but adding one literal query checks the DQL wrapper with inline WKT (per project patterns).

Example method to append:

#[Test]
public function returns_envelope_from_wkt_literal(): void
{
    $dql = "SELECT ST_AREA(ST_ENVELOPE('LINESTRING(0 0, 2 2)')) as result";
    $result = $this->executeDqlQuery($dql);
    $this->assertEqualsWithDelta(4.0, (float) $result[0]['result'], 1.0E-12);
}

Also applies to: 23-54

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 13ee267 and 9d2d952.

📒 Files selected for processing (2)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DPerimeterTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_EnvelopeTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DPerimeterTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_EnvelopeTest.php
📚 Learning: 2025-08-27T18:19:35.789Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DPerimeterTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_EnvelopeTest.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DPerimeterTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_EnvelopeTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DPerimeterTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_EnvelopeTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DPerimeterTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_EnvelopeTest.php
📚 Learning: 2025-04-22T00:03:37.733Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DPerimeterTest.php
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.4
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.3
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.1
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.3
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: sloth
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.18 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.1 + Doctrine ORM latest + Doctrine Lexer 2.1
  • GitHub Check: wait-for-tests-worflows-before-upload
🔇 Additional comments (4)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_3DPerimeterTest.php (1)

12-17: Registration of DQL function looks correct.

Mapping 'ST_3DPERIMETER' to ST_3DPerimeter::class matches the project's conventions and should wire the function properly for DQL.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_EnvelopeTest.php (3)

1-5: Good: strict types and namespace match project patterns

Header looks consistent with other Integration tests in this repo. No issues.


14-21: Function registration map looks correct

Aliases (ST_AREA, ST_ENVELOPE, ST_EQUALS) match the DQL used below and the wrapper classes. Nice and consistent.


23-33: No change required — DBAL already returns booleans

executeDqlQuery (tests/Integration/MartinGeorgiev/TestCase.php) uses getArrayResult, and existing tests (e.g. tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RelateMatchTest.php) assertIsBool/assertTrue, so casting to (bool) is unnecessary.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (10)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DifferenceTest.php (4)

26-32: Fix minor typo in assertion message

Double space in "correct difference".

Apply this diff:

-        $this->assertEquals(12, $result[0]['result'], 'should calculate correct  difference area: outer polygon minus inner polygon');
+        $this->assertEquals(12, $result[0]['result'], 'should calculate correct difference area: outer polygon minus inner polygon');

37-43: Clarify assertion message: polygons are equal-sized, not larger/smaller

The polygons at id=4 are both 2x2; only partial overlap differs. Adjust wording to avoid confusion.

Apply this diff:

-        $this->assertEquals(3, $result[0]['result'], 'should calculate correct  difference area: smaller polygon minus overlapping larger polygon');
+        $this->assertEquals(3, $result[0]['result'], 'should calculate correct difference area: 2x2 square minus partially overlapping 2x2 square');

52-54: Relax delta to avoid fragile float comparisons across PostGIS/GEOS builds

1e-16 is unnecessarily tight; 1e-12 keeps the test robust while remaining strict.

Apply this diff:

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.0000000000000001, 'should preserve original linestring length when geometries do not overlap');
+        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 1e-12, 'should preserve original linestring length when geometries do not overlap');

55-55: Optional: add two edge-case assertions (contained polygon -> empty; boundary-touching -> unchanged)

These strengthen coverage for overlay behavior without complicating setup (ids 6 and 8 already exist in fixtures).

Apply this diff:

 }
+
+    #[Test]
+    public function returns_empty_when_first_polygon_is_contained_in_second(): void
+    {
+        $dql = 'SELECT ST_AREA(ST_DIFFERENCE(g.geometry1, g.geometry2)) as result
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
+                WHERE g.id = 6';
+
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEquals(0, $result[0]['result'], 'difference should be empty when the first polygon is fully contained in the second');
+    }
+
+    #[Test]
+    public function returns_same_polygon_when_touching_at_boundary(): void
+    {
+        $dql = 'SELECT ST_AREA(ST_DIFFERENCE(g.geometry1, g.geometry2)) as result
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
+                WHERE g.id = 8';
+
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEquals(4, $result[0]['result'], 'difference should equal the original polygon when polygons only touch along a boundary');
+    }
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyTest.php (5)

13-23: Optional: add parity tests for ST_Simplify variants.

Given this PR adds ST_SimplifyVW and ST_SimplifyPreserveTopology, consider adding companion integration tests (either here or separate classes) for coverage symmetry.


28-34: Relax the delta to avoid cross-version numeric flakiness.

PostGIS floating ops can vary at the ulp level across versions/GEOS builds. A 1e-9–1e-12 tolerance is typically sufficient and stabler than 1e-16.

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.0000000000000001, 'should preserve length for straight linestrings');
+        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 1e-9, 'should preserve length for straight linestrings');

39-45: Use a small delta for area too.

Even with integer coordinates, simplification/area can differ by machine epsilon in some environments.

-        $this->assertEquals(16, $result[0]['result'], 'should preserve area for rectangular polygons');
+        $this->assertEqualsWithDelta(16.0, $result[0]['result'], 1e-12, 'should preserve area for rectangular polygons');

50-56: Cast to bool in assertion for driver portability.

Doctrine/pgsql may hydrate scalar boolean expressions as 't'/'f' strings in some configurations. Casting prevents brittle failures.

-        $this->assertTrue($result[0]['result'], 'should return unchanged point for point geometries');
+        $this->assertTrue((bool) $result[0]['result'], 'should return unchanged point for point geometries');

25-34: Optional: assert actual simplification effect.

Beyond preserving length, consider verifying vertex reduction (e.g., ST_NPoints(ST_SimplIFY(...)) = 2) or equality to 'LINESTRING(0 0, 2 2)' to confirm DP removed the middle vertex. Add the needed function mapping if not already present.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php (1)

29-29: Make assertions resilient to float representation differences.

Use delta-based assertions to avoid brittle failures across PostGIS/driver versions.

-        $this->assertEquals(16, $result[0]['result'], 'boundary of POLYGON((0 0, 0 4, 4 4, 4 0, 0 0)) should be a LineString with perimeter = 16');
+        $this->assertEqualsWithDelta(16.0, (float) $result[0]['result'], 1e-6, 'boundary of POLYGON((0 0, 0 4, 4 4, 4 0, 0 0)) should be a LineString with perimeter ≈ 16');
@@
-        $this->assertEquals(0, $result[0]['result'], 'boundary of linestring should return MultiPoint with zero length');
+        $this->assertEqualsWithDelta(0.0, (float) $result[0]['result'], 0.0, 'boundary of linestring should return MultiPoint with zero length');
@@
-        $this->assertEquals(0, $result[0]['result'], 'boundary of point should return empty geometry with zero length');
+        $this->assertEqualsWithDelta(0.0, (float) $result[0]['result'], 0.0, 'boundary of point should return empty geometry with zero length');

Also applies to: 40-40, 51-51

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9d2d952 and ce6f90f.

📒 Files selected for processing (3)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DifferenceTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DifferenceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DifferenceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DifferenceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php
📚 Learning: 2025-08-27T18:19:35.789Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DifferenceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DifferenceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php
📚 Learning: 2025-04-22T00:03:37.733Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyTest.php
🧬 Code graph analysis (3)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyTest.php (5)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Equals.php (1)
  • ST_Equals (22-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Simplify.php (1)
  • ST_Simplify (23-31)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DifferenceTest.php (5)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Difference.php (1)
  • ST_Difference (23-31)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php (4)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Boundary.php (1)
  • ST_Boundary (25-32)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.4
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.3
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.1
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.2
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.14 + Doctrine Lexer 1.2
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: sloth
  • GitHub Check: wait-for-tests-worflows-before-upload
🔇 Additional comments (6)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_DifferenceTest.php (1)

14-21: Function registration mapping looks correct

Aliases and class mappings align with the DQL used in this test.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SimplifyTest.php (2)

7-11: Imports are tight and accurate.

Only the functions used by the tests are imported; no strays.


15-23: Function registration looks consistent with project patterns.

Uppercased keys and mapped classes align with other tests in this suite.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php (3)

13-19: String function mappings look correct and consistent.

Mappings to ST_Boundary and ST_Length match the wrappers’ prototypes and the project’s established pattern. Fixture path usage aligns with prior learnings for this codebase.


24-30: Polygon boundary length assertion is sound.

For SRID=4326 geometry, ST_Length returns planar degrees; the square’s perimeter is 16 as asserted.


35-41: Linestring case is correct.

Topological boundary of an open LineString is a MultiPoint; its length is 0.

Comment on lines +7 to +9
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Boundary;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Length;
use PHPUnit\Framework\Attributes\Test;
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

Align test name with behavior: also assert boundary is empty for point.

Add ST_IsEmpty mapping and assert emptiness to match the method name and tighten intent.

Apply:

@@
-use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Boundary;
-use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Length;
+use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Boundary;
+use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Length;
+use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_IsEmpty;
@@
         return [
             'ST_BOUNDARY' => ST_Boundary::class,
             'ST_LENGTH' => ST_Length::class,
+            'ST_ISEMPTY' => ST_IsEmpty::class,
         ];
@@
-        $dql = 'SELECT ST_LENGTH(ST_BOUNDARY(g.geometry1)) as result
+        $dql = 'SELECT ST_LENGTH(ST_BOUNDARY(g.geometry1)) as result, ST_ISEMPTY(ST_BOUNDARY(g.geometry1)) as is_empty
                 FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
                 WHERE g.id = 1';
 
         $result = $this->executeDqlQuery($dql);
-        $this->assertEquals(0, $result[0]['result'], 'boundary of point should return empty geometry with zero length');
+        $this->assertEquals(0, $result[0]['result'], 'boundary of point should return empty geometry with zero length');
+        $this->assertTrue((bool) $result[0]['is_empty'], 'boundary of point should be empty');

If ST_IsEmpty isn’t in this PR, either add its wrapper or rename the test to “returns_zero_length_for_point_boundary”.

To verify the wrapper exists:

Also applies to: 13-19, 46-52


🏁 Script executed:

#!/bin/bash
# Check for ST_IsEmpty wrapper
rg -nP 'class\s+ST_IsEmpty\b' -g 'src/**/PostGIS/*.php' -C2

Length of output: 61


🏁 Script executed:

#!/bin/bash
# Search for ST_IsEmpty class definition anywhere in src/
rg -nP 'class\s+ST_IsEmpty\b' -C2 src
# Search for ST_ISEMPTY constant or mapping usage
rg -n 'ST_ISEMPTY' -C2 src
# List files with "ST_IsEmpty" in their filename
fd 'ST_IsEmpty' -t f

Length of output: 87


Add missing ST_IsEmpty wrapper or rename test to “returns_zero_length_for_point_boundary”
No AST function class ST_IsEmpty exists in src/, so the new mapping and assertion won’t compile. Either implement ST_IsEmpty under src/…/PostGIS/ST_IsEmpty.php (and register it in the function mappings) or update tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php to remove all ST_ISEMPTY references and rename the test accordingly.

🤖 Prompt for AI Agents
In
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_BoundaryTest.php
around lines 7 to 9, the test references an AST function ST_IsEmpty which does
not exist in src/, causing compilation failures; either add a new AST function
class at
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IsEmpty.php
implementing the required interface and behavior and register it in the function
mappings used by the tests, or modify this test to remove all ST_ISEMPTY
references and rename the test to “returns_zero_length_for_point_boundary” so it
asserts the expected zero length without relying on ST_IsEmpty.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2DTest.php (5)

37-37: Unify function name casing with registry

DQL uses ST_Envelope while the registry key is ST_ENVELOPE. Doctrine is case-insensitive, but prefer consistent casing to avoid surprises in future refactors.

-        $dql = 'SELECT ST_AREA(ST_CLIPBYBOX2D(g.geometry1, ST_Envelope(g.geometry1))) as result
+        $dql = 'SELECT ST_AREA(ST_CLIPBYBOX2D(g.geometry1, ST_ENVELOPE(g.geometry1))) as result

30-32: Prefer delta-based float assertion

Avoid strict equality on floats; use a small delta.

-        $this->assertEquals(16, $result[0]['result']);
+        $this->assertEqualsWithDelta(16.0, (float) $result[0]['result'], 1e-9);

41-43: Prefer delta-based float assertion

Same reasoning as above.

-        $this->assertEquals(16, $result[0]['result']);
+        $this->assertEqualsWithDelta(16.0, (float) $result[0]['result'], 1e-9);

52-54: Prefer delta-based float assertion

Apply delta-based comparison here too.

-        $this->assertEquals(16, $result[0]['result']);
+        $this->assertEqualsWithDelta(16.0, (float) $result[0]['result'], 1e-9);

45-53: Use existing Cast function to ensure proper parameter typing
The repo already provides a Cast AST function (src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cast.php), so modify the DQL to cast the :box_param placeholder to box2d, for example:

$dql = '
  SELECT ST_AREA(
    ST_ClipByBox2D(g.geometry1, CAST(:box_param AS box2d))
  ) AS result
  FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
  WHERE g.id = 2
';

This guarantees PostGIS resolves the correct overload and prevents “function ST_ClipByBox2D(geometry, text) does not exist” errors on stricter PG/PostGIS versions.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ce6f90f and 8a1b637.

📒 Files selected for processing (1)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2DTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2DTest.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2DTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2DTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2DTest.php
🧬 Code graph analysis (1)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2DTest.php (5)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2D.php (1)
  • ST_ClipByBox2D (23-31)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Envelope.php (1)
  • ST_Envelope (23-30)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: PHP 8.3 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM 3.0 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.18 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.18 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.1 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.1 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.1 + Doctrine ORM 3.0 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.1 + Doctrine ORM latest + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: wait-for-tests-worflows-before-upload
🔇 Additional comments (2)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ClipByBox2DTest.php (2)

1-11: LGTM: scaffolding/imports look correct

Namespace, strict_types, and PHPUnit attribute usage are consistent with the project’s Integration tests.


14-21: LGTM: function registrations align with wrappers

Mappings for ST_AREA, ST_CLIPBYBOX2D, and ST_ENVELOPE are correct and minimal.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (7)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineCrossingDirectionTest.php (1)

81-84: Avoid brittle magic number; derive expected row count or assert non-empty.

The WHERE clause uses a constant true predicate (function with literal args), so the result size equals the total rows in ContainsGeometries. Hardcoding 10 ties the test to fixture size and will break when fixtures change.

Option A (derive expected count):

-        $this->assertCount(10, $result);
+        // Constant predicate → returns all rows. Derive expected count from the fixture.
+        $count = $this->executeDqlQuery(
+            'SELECT COUNT(g.id) AS c FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g'
+        );
+        $this->assertCount((int) $count[0]['c'], $result);

Option B (looser but stable):

-        $this->assertCount(10, $result);
+        $this->assertNotEmpty($result);
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TranslateTest.php (4)

28-34: Relax tolerance to avoid float flakiness

Delta 1e-16 is too strict for platform/PostGIS differences. 1e-12 is typically safe while still precise.

Apply:

-        $this->assertEqualsWithDelta(14.142135623730951, $result[0]['result'], 0.0000000000000001, 'ST_Translate should move point by expected distance');
+        $this->assertEqualsWithDelta(14.142135623730951, $result[0]['result'], 1e-12, 'ST_Translate should move point by expected distance');

39-45: Use a delta for area as well

Even trivial polygon areas can differ by a few ulps across environments. Use a small delta.

Apply:

-        $this->assertEquals(16, $result[0]['result'], 'ST_Translate should preserve polygon area');
+        $this->assertEqualsWithDelta(16.0, $result[0]['result'], 1e-12, 'ST_Translate should preserve polygon area');

50-56: Relax tolerance here too

Same reasoning as the point distance case.

Apply:

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.0000000000000001, 'ST_Translate should preserve linestring length');
+        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 1e-12, 'ST_Translate should preserve linestring length');

21-21: Consider parameterizing dx/dy to match real-world usage

Currently tests (and ST_Translate mapping) rely on numeric literals for dx/dy. If we want to support bound parameters, extend the ST_Translate node mapping to accept input parameters for the second and third args, then add a companion test here that binds them.

Proposed follow-ups:

  • In ST_Translate (outside this file), allow parameters for dx/dy (e.g., accept InputParameter/SimpleArithmeticExpression as per project conventions).
  • Add an extra test:
#[Test]
public function translates_point_by_offset_with_params(): void
{
    $dql = 'SELECT ST_DISTANCE(g.geometry1, ST_TRANSLATE(g.geometry1, :dx, :dy)) AS result
            FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
            WHERE g.id = 1';

    $result = $this->executeDqlQuery($dql, ['dx' => 10.0, 'dy' => 10.0]);
    $this->assertEqualsWithDelta(14.142135623730951, $result[0]['result'], 1e-12);
}
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLineTest.php (2)

25-34: Loosen the numeric delta to avoid cross-platform flakiness.

ST_Length over float8 can vary slightly across PostGIS/CPU. A tolerance of 1e-12 is usually safer than 1e-16.

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.0000000000000001, 'should preserve length for straight linestrings');
+        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 1.0e-12, 'should preserve length for straight linestrings');

25-34: Add one projected-SRID length check (optional).

Row id=10 in the shared fixture uses SRID 3857 with a 2km polyline. Verifying preservation in projected units strengthens coverage.

     #[Test]
     public function converts_curve_to_line(): void
     {
         $dql = 'SELECT ST_LENGTH(ST_CURVETOLINE(g.geometry1)) as result
                 FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
                 WHERE g.id = 3';

         $result = $this->executeDqlQuery($dql);
         $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 1.0e-12, 'should preserve length for straight linestrings');
     }
+
+    #[Test]
+    public function preserves_length_in_projected_srid(): void
+    {
+        $dql = 'SELECT ST_LENGTH(ST_CURVETOLINE(g.geometry1)) as result
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
+                WHERE g.id = 10';
+
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(2000.0, $result[0]['result'], 1.0e-9, 'should preserve length in meters for SRID 3857 linestrings');
+    }

Also applies to: 36-45

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8a1b637 and 2ceba28.

📒 Files selected for processing (4)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLineTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineCrossingDirectionTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TranslateTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineCrossingDirectionTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLineTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TranslateTest.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLineTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TranslateTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLineTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TranslateTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLineTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TranslateTest.php
📚 Learning: 2025-04-22T00:03:37.733Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TranslateTest.php
📚 Learning: 2025-03-11T12:32:10.726Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#263
File: src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Numrange.php:19-21
Timestamp: 2025-03-11T12:32:10.726Z
Learning: In the postgresql-for-doctrine repository, PostgreSQL range functions have distinct implementations for different data types. The `Numrange` function works with numeric/decimal values and is tested using the `ContainsDecimals` fixture with properties typed as `float`. In contrast, the `Int4range` function works with 32-bit integers and is tested using the `ContainsIntegers` fixture with properties typed as `int`. While the PHP implementations share a similar structure (extending `BaseFunction`), they are semantically different as they handle different PostgreSQL data types.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php
📚 Learning: 2025-08-27T18:19:35.789Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLineTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TranslateTest.php
🧬 Code graph analysis (3)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php (6)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Equals.php (1)
  • ST_Equals (22-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Subdivide.php (1)
  • ST_Subdivide (23-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLineTest.php (6)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLine.php (1)
  • ST_CurveToLine (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Equals.php (1)
  • ST_Equals (22-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TranslateTest.php (6)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Distance.php (1)
  • ST_Distance (23-31)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Translate.php (1)
  • ST_Translate (23-32)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.1
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.14 + Doctrine Lexer 1.2
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM latest + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.18 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.1 + Doctrine ORM latest + Doctrine Lexer latest
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: sloth
  • GitHub Check: wait-for-tests-worflows-before-upload
🔇 Additional comments (4)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_TranslateTest.php (1)

15-23: Function registration looks good

The string-function map is consistent with the suite and sufficient for these tests.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CurveToLineTest.php (2)

15-23: String-function mapping is correct and consistent.

Mappings align with the wrappers in src and match the DQL usage below.


47-56: No change required
PHPUnit’s assertTrue() requires a native true, and Doctrine DBAL’s boolean type always hydrates to a PHP bool by default(doctrine-project.org). Casting to (bool) only becomes necessary if you explicitly configure PostgreSqlPlatform to return string literals (“t”/“f”), which isn’t the default.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php (1)

15-23: SRF registration infrastructure missing: the codebase has no getTableFunctions() method, TableFunction classes, or SRF-registration support—so you can’t simply reassign ST_SUBDIVIDE as a table function. Add proper SRF/table-function registration (e.g. define getTableFunctions(), base TableFunction types, parser/compiler hooks) before removing ST_SUBDIVIDE from getStringFunctions().

Likely an incorrect or invalid review comment.

Comment on lines +28 to +33
$dql = 'SELECT ST_AREA(ST_SUBDIVIDE(g.geometry1, 10)) as result
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
WHERE g.id = 2';

$result = $this->executeDqlQuery($dql);
$this->assertEquals(16, $result[0]['result']);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Invalid scalar use: ST_AREA(ST_SUBDIVIDE(...))

ST_Subdivide yields a set; passing it to ST_Area directly is invalid. Use the table function in FROM/LATERAL and aggregate areas (also consider forcing an actual subdivision for this case).

-        $dql = 'SELECT ST_AREA(ST_SUBDIVIDE(g.geometry1, 10)) as result
-                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
-                WHERE g.id = 2';
+        // Aggregate area over subdivided pieces (adapt table-function join syntax to your extension):
+        $dql = 'SELECT SUM(ST_AREA(s)) AS result
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g, ST_SUBDIVIDE(g.geometry1, 3) s
+                WHERE g.id = 2';
📝 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
$dql = 'SELECT ST_AREA(ST_SUBDIVIDE(g.geometry1, 10)) as result
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
WHERE g.id = 2';
$result = $this->executeDqlQuery($dql);
$this->assertEquals(16, $result[0]['result']);
// Aggregate area over subdivided pieces (adapt table-function join syntax to your extension):
$dql = 'SELECT SUM(ST_AREA(s)) AS result
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g, ST_SUBDIVIDE(g.geometry1, 3) s
WHERE g.id = 2';
$result = $this->executeDqlQuery($dql);
$this->assertEquals(16, $result[0]['result']);
🤖 Prompt for AI Agents
In
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php
around lines 28–33, the test incorrectly nests ST_SUBDIVIDE inside ST_AREA
(ST_SUBDIVIDE returns a set), so change the query to treat ST_SUBDIVIDE as a
table function (FROM / LATERAL) and aggregate the areas; e.g. cross-join the
subdivision output as rows, compute ST_AREA on each row and SUM those areas in
the SELECT, and if needed adjust the subdivision parameter to force an actual
subdivision for this test case.

Comment on lines +39 to +45
$dql = 'SELECT ST_LENGTH(ST_SUBDIVIDE(g.geometry1, 10)) as result
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
WHERE g.id = 3';

$result = $this->executeDqlQuery($dql);
$this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.0000000000000001);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Invalid scalar use: ST_LENGTH(ST_SUBDIVIDE(...))

Same issue. Sum lengths of pieces produced by the table function. Consider lowering the vertex cap to actually trigger subdivision.

-        $dql = 'SELECT ST_LENGTH(ST_SUBDIVIDE(g.geometry1, 10)) as result
-                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
-                WHERE g.id = 3';
+        $dql = 'SELECT SUM(ST_LENGTH(s)) AS result
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g, ST_SUBDIVIDE(g.geometry1, 2) s
+                WHERE g.id = 3';

For numerical robustness across platforms, relax the delta slightly (e.g., 1e-12).

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.0000000000000001);
+        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 1.0e-12);
📝 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
$dql = 'SELECT ST_LENGTH(ST_SUBDIVIDE(g.geometry1, 10)) as result
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
WHERE g.id = 3';
$result = $this->executeDqlQuery($dql);
$this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.0000000000000001);
}
$dql = 'SELECT SUM(ST_LENGTH(s)) AS result
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g, ST_SUBDIVIDE(g.geometry1, 2) s
WHERE g.id = 3';
$result = $this->executeDqlQuery($dql);
$this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 1.0e-12);

Comment on lines +50 to +56
$dql = 'SELECT ST_EQUALS(ST_SUBDIVIDE(g.geometry1, 100), g.geometry1) as result
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
WHERE g.id = 1';

$result = $this->executeDqlQuery($dql);
$this->assertTrue($result[0]['result']);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Reassemble pieces before equality check

Equality must compare a single geometry. Union (or collect+unary-union) the subdivided pieces first, then compare to the original.

-        $dql = 'SELECT ST_EQUALS(ST_SUBDIVIDE(g.geometry1, 100), g.geometry1) as result
-                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
-                WHERE g.id = 1';
+        $dql = 'SELECT ST_EQUALS(ST_UNION(s), g.geometry1) AS result
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g, ST_SUBDIVIDE(g.geometry1, 100) s
+                WHERE g.id = 1';
📝 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
$dql = 'SELECT ST_EQUALS(ST_SUBDIVIDE(g.geometry1, 100), g.geometry1) as result
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
WHERE g.id = 1';
$result = $this->executeDqlQuery($dql);
$this->assertTrue($result[0]['result']);
}
$dql = 'SELECT ST_EQUALS(ST_UNION(s), g.geometry1) AS result
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g, ST_SUBDIVIDE(g.geometry1, 100) s
WHERE g.id = 1';
$result = $this->executeDqlQuery($dql);
$this->assertTrue($result[0]['result']);
🤖 Prompt for AI Agents
In
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SubdivideTest.php
around lines 50-56, the test compares the original geometry to the array of
subdivided pieces directly; instead, reassemble the subdivided pieces into a
single geometry before equality check. Change the DQL to wrap ST_SUBDIVIDE(...)
with a reassembly function—e.g. use ST_UNION(ST_SUBDIVIDE(g.geometry1, 100)) or
ST_UNARY_UNION(ST_COLLECT(ST_SUBDIVIDE(g.geometry1, 100)))—so the query compares
one geometry to one geometry, then assert the result as before.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (11)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ReverseTest.php (3)

25-34: Relax the delta to avoid flakiness across PostGIS/GEOS builds.

1e-16 is extremely tight; minor numeric drift between environments can fail this. Suggest 1e-12 (or 1e-9) which is still strict but resilient.

Apply:

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.0000000000000001, 'should preserve linestring length');
+        $this->assertEqualsWithDelta(2.8284271247461903, (float)$result[0]['result'], 1e-12, 'should preserve linestring length');

36-45: Use a delta for area as well.

Area should be preserved, but exact-equality can be brittle across versions/compilers. Prefer a small delta.

Apply:

-        $this->assertEquals(16, $result[0]['result'], 'should preserve polygon area');
+        $this->assertEqualsWithDelta(16.0, (float)$result[0]['result'], 1e-12, 'should preserve polygon area');

47-56: Normalize boolean result to guard against driver return types.

Some DBAL versions can return 't'/'f' or '1'/'0'. Casting ensures stable assertion semantics without changing intent.

Apply:

-        $this->assertTrue($result[0]['result'], 'should return unchanged point for point geometries');
+        $this->assertTrue((bool)$result[0]['result'], 'should return unchanged point for point geometries');
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force2DTest.php (2)

47-56: Relax tolerance and cast defensively for length comparison

Length values can vary slightly across PostGIS/GEOS versions and driver conversions. The current 1e-15 delta is overly tight and may cause flakes. Also, ensure numeric comparison.

Apply:

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.000000000000001, 'should preserve linestring length');
+        $this->assertEqualsWithDelta(2.8284271247461903, (float) $result[0]['result'], 1e-9, 'should preserve linestring length');

15-23: Optional: add an explicit “Z dropped” assertion using ST_NDims

To validate the core contract of ST_Force2D, consider asserting dimensionality change on a 3D literal. Per prior learnings in this repo, WKT literals can be used directly in DQL without ST_GeomFromText wrapping. I can draft this if ST_NDims is part of the PR.

Example (requires mapping ST_NDIMS => ST_NDims::class and import):

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_NDims;

// in getStringFunctions():
'ST_NDIMS' => ST_NDims::class,

Add a test method:

#[Test]
public function drops_z_dimension(): void
{
    $dql = "SELECT ST_NDIMS(ST_FORCE2D('POINT Z (1 2 3)')) as result";
    $result = $this->executeDqlQuery($dql);
    $this->assertSame(2, (int) $result[0]['result'], 'should reduce dimensionality to 2D');
}

This avoids fixture dependency and directly proves Z removal.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ConvexHullTest.php (3)

25-34: Type-assert the boolean result before asserting truthiness.

Preempt subtle hydration differences by asserting the type explicitly.

         $result = $this->executeDqlQuery($dql);
-        $this->assertTrue($result[0]['result'], 'convex hull of a point should be the point itself');
+        $this->assertIsBool($result[0]['result']);
+        $this->assertTrue($result[0]['result'], 'convex hull of a point should be the point itself');

39-45: Use delta-based comparison for area to avoid float precision traps.

Even when expecting an exact 16, DB drivers may return float(16). Prefer a tolerant check.

-        $this->assertEquals(16, $result[0]['result'], 'convex hull should preserve area for rectangular polygons');
+        $this->assertEqualsWithDelta(16.0, (float) $result[0]['result'], 1e-12, 'convex hull should preserve area for rectangular polygons');

50-56: Relax delta and derive the expected length inline for clarity.

1e-16 is tighter than typical double precision tolerance across platforms. Derive sqrt(8) for readability and use a looser delta.

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.0000000000000001, 'convex hull should preserve length for collinear linestring');
+        $this->assertEqualsWithDelta(\sqrt(8), (float) $result[0]['result'], 1e-9, 'convex hull should preserve length for a collinear linestring');
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineToCurveTest.php (3)

32-34: Relax tolerance and cast result to float to avoid flakiness across PostGIS/GEOS versions

Tiny numeric drifts are common between environments. Casting ensures numeric comparison and using a scientific notation improves readability.

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.000000000000001, 'should preserve linestring length');
+        $result = $this->executeDqlQuery($dql);
+        $value  = (float) $result[0]['result'];
+        $this->assertEqualsWithDelta(2.8284271247461903, $value, 1e-12, 'should preserve linestring length');

Additionally, consider adding a sibling test that uses a WKT literal directly to reduce fixture coupling (per prior learnings in this repo).


43-45: Use delta-based comparison for area as well

Area can also exhibit tiny rounding differences; keep assertions stable across PostGIS versions.

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEquals(16, $result[0]['result'], 'should preserve polygon area');
+        $result = $this->executeDqlQuery($dql);
+        $value  = (float) $result[0]['result'];
+        $this->assertEqualsWithDelta(16.0, $value, 1e-12, 'should preserve polygon area');

13-23: Optional: add a type-stability check for curved outputs

If you want extra confidence, add a test asserting the curved geometry type for line/polygon inputs (e.g., CurvePolygon/CompoundCurve) while keeping point unchanged. This can help catch regressions in wrapper-to-SQL translation.

Also applies to: 25-56

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2ceba28 and 99cd11c.

📒 Files selected for processing (4)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ConvexHullTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force2DTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineToCurveTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ReverseTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#0
File: :0-0
Timestamp: 2025-08-24T16:52:32.488Z
Learning: All new features in this repository must include proper test coverage before approval - this ltree implementation demonstrates exemplary test coverage with comprehensive unit tests, integration tests, data providers for edge cases, and validation of all relationships and error conditions.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ReverseTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ConvexHullTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineToCurveTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force2DTest.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ReverseTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ConvexHullTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineToCurveTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force2DTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ReverseTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ConvexHullTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineToCurveTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force2DTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ReverseTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ConvexHullTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineToCurveTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force2DTest.php
📚 Learning: 2025-08-27T18:19:35.789Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ReverseTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ConvexHullTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineToCurveTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force2DTest.php
📚 Learning: 2025-04-22T00:03:37.733Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force2DTest.php
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.4
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.3
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.1
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.2
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.2
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.18 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer 2.1
  • GitHub Check: sloth
  • GitHub Check: wait-for-tests-worflows-before-upload
🔇 Additional comments (13)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ReverseTest.php (2)

13-13: Solid test scaffold and naming.

Extends the expected SpatialOperatorTestCase and follows the Integration/PostGIS namespace and fixture usage pattern from earlier PRs. Looks consistent with prior tests (per retrieved learnings).


15-23: Confirmed: SpatialOperatorTestCase only defines getStringFunctions; there’s no getNumericFunctions hook, so no changes needed.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Force2DTest.php (4)

15-23: Function map looks correct and consistent

Mappings for ST_AREA, ST_EQUALS, ST_FORCE2D, and ST_LENGTH are aligned with existing patterns. No issues spotted.


25-34: Boolean result typing: confirm executeDqlQuery returns native bool

Depending on DBAL hydration, PostgreSQL booleans may come back as 't'/'f' strings. Verify that executeDqlQuery normalizes booleans; otherwise this assertion could misbehave.

If normalization isn’t guaranteed, consider asserting explicitly on string/boolean:

-        $this->assertTrue($result[0]['result'], 'should return unchanged 2D point');
+        $this->assertTrue($result[0]['result'] === true || $result[0]['result'] === 't', 'should return unchanged 2D point');

36-45: LGTM: area preservation scenario is clear

The polygon area check (expected 16) is straightforward and fits the fixture-driven pattern.


11-13: Attribute support confirmed
composer.json specifies PHPUnit ^10.5.53 on PHP ^8.1+, and #[Test] is already used consistently across the test suite. No changes needed.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ConvexHullTest.php (2)

15-23: Function registration mapping looks good.

The DQL-to-wrapper mapping for ST_AREA, ST_CONVEXHULL, ST_EQUALS, and ST_LENGTH is consistent with patterns in this repo.


25-56: PHPUnit 10 is already required (composer.json: ^10.5.53), so the #[Test] attribute is supported.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_LineToCurveTest.php (5)

1-4: Good: strict types and file preamble are in place

Nothing to change here.


5-11: Namespace and imports look correct for the project conventions

The wrapper imports and the PHPUnit attribute are appropriately scoped.


15-23: Function registrations match DQL usage

The keys align with the DQL invocations in this test.


50-56: Boolean assertion reads clearly and is strict

assertTrue here is appropriate; result mapping from PostgreSQL booleans should keep this strict.


7-11: No changes required; ST_LineToCurve wrapper and fixtures verified.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (14)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CentroidTest.php (2)

47-56: Use tolerance for floating-point distance.

Distance may be rendered as 0 or a tiny epsilon depending on PostGIS/GEOS versions. Prefer a delta-based assertion to avoid flakiness.

-        $this->assertEquals(0, $result[0]['result'], 'should return point on linestring (distance = 0)');
+        $this->assertEqualsWithDelta(0.0, (float) $result[0]['result'], 1.0e-9, 'centroid should lie on straight linestring');

58-67: Rename: these are nested/concentric polygons, not “overlapping”.

Fixture id=2 contains a square and a concentric inner square (same centroid). Either rename for accuracy or switch to id=4 if you want a true overlap (centroids differ).

Rename-only option:

-    public function returns_centroid_for_overlapping_polygons(): void
+    public function returns_centroid_for_nested_polygons(): void

(Optional) Add a separate negative test with id=4 asserting centroids are not equal if you want coverage for overlapping polygons.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IntersectionTest.php (2)

23-33: Use a delta and cast for numeric robustness.

PostgreSQL/Doctrine may return numeric results as strings and floating ops can introduce tiny errors. Cast and use a delta to avoid flaky tests.

-        $this->assertEquals(1, $result[0]['result'], 'should calculate correct overlapping area between polygons');
+        $this->assertEqualsWithDelta(1.0, (float) $result[0]['result'], 1e-9, 'should calculate correct overlapping area between polygons');

If your PHPUnit version doesn’t support assertEqualsWithDelta, keep the cast and plain assertEquals.


45-54: Ensure boolean assertion is resilient across drivers.

Depending on hydration, result may be 't'/'f', 1/0, or true/false. Casting keeps the intent explicit.

-        $this->assertTrue($result[0]['result'], 'intersection of identical geometries should equal the original geometry');
+        $this->assertTrue((bool) $result[0]['result'], 'intersection of identical geometries should equal the original geometry');
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RotateTest.php (4)

25-34: Make the point-distance assertion tolerant to FP jitter.

Rotation is rigid, but DB math can return tiny epsilons. Use a delta to avoid flakes.

Apply:

-        $this->assertEquals(0, $result[0]['result'], 'should not move point at origin');
+        $this->assertEqualsWithDelta(0.0, $result[0]['result'], 1e-12, 'should not move point at origin');

36-45: Relax the area assertion tolerance.

The current 2e-15 margin is unnecessarily tight and may be platform-version sensitive.

Apply:

-        $this->assertEqualsWithDelta(16, $result[0]['result'], 0.000000000000002, 'should preserve polygon area');
+        $this->assertEqualsWithDelta(16.0, $result[0]['result'], 1e-12, 'should preserve polygon area');

47-56: Relax the length assertion tolerance.

As above, loosen epsilon to reduce spurious failures across PostGIS versions.

Apply:

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.000000000000001, 'should preserve linestring length');
+        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 1e-12, 'should preserve linestring length');

28-31: Optional: allow parameterized angles in DQL (then add a test variant).

If we want to pass angles as parameters (e.g., :angle computed via PHP’s pi()), the ST_Rotate wrapper needs to accept InputParameter in addition to Literal. Once enabled, add a companion test using a bound parameter to cover that path.

Also applies to: 39-42, 50-53

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SplitTest.php (3)

21-30: Relax tolerance and cast result to float to avoid precision flakes.

Delta 1e-15 is unnecessarily tight for DB/GEOS-backed computations; some platforms may differ by a few ulps. Casting guards against PDO returning numeric strings.

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEqualsWithDelta(5.656854249492381, $result[0]['result'], 0.000000000000001, 'should preserve total linestring length');
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(5.656854249492381, (float) $result[0]['result'], 1.0E-12, 'should preserve total linestring length');

32-41: Apply the same tolerance/cast here for consistency.

Mirrors the previous test; reduces risk of sporadic failures.

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.000000000000001, 'should preserve linestring length when no split occurs');
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(2.8284271247461903, (float) $result[0]['result'], 1.0E-12, 'should preserve linestring length when no split occurs');

24-26: Optional: parameterize IDs to match common DQL patterns and readability.

Keeps DQL consistent with other integration tests and highlights the variable part of the query.

-        $dql = 'SELECT ST_LENGTH(ST_SPLIT(g.geometry1, g.geometry2)) as result
-                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
-                WHERE g.id = 9';
-
-        $result = $this->executeDqlQuery($dql);
+        $dql = 'SELECT ST_LENGTH(ST_SPLIT(g.geometry1, g.geometry2)) as result
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
+                WHERE g.id = :id';
+
+        $result = $this->executeDqlQuery($dql, ['id' => 9]);
-        $dql = 'SELECT ST_LENGTH(ST_SPLIT(g.geometry1, g.geometry2)) as result
-                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
-                WHERE g.id = 3';
-
-        $result = $this->executeDqlQuery($dql);
+        $dql = 'SELECT ST_LENGTH(ST_SPLIT(g.geometry1, g.geometry2)) as result
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
+                WHERE g.id = :id';
+
+        $result = $this->executeDqlQuery($dql, ['id' => 3]);

Also applies to: 28-28, 35-37, 39-39

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ScaleTest.php (3)

25-34: Cast the boolean result for robustness across hydrators.

Depending on platform/type mappings, PostgreSQL booleans may arrive as 't'/'f' strings. Casting avoids brittle assertions.

-        $this->assertTrue($result[0]['result'], 'should return unchanged point at origin (0 * factor = 0)');
+        $this->assertTrue((bool) $result[0]['result'], 'should return unchanged point at origin (0 * factor = 0)');

36-45: Avoid magic numbers and relax delta slightly to prevent flakiness.

Compute the expected area and use a less brittle tolerance; double math across ST_Scale/Area can drift at 1e-15.

         $result = $this->executeDqlQuery($dql);
-        $this->assertEqualsWithDelta(36, $result[0]['result'], 0.000000000000001, 'should scale polygon area by factor squared (16 * 1.5 * 1.5 = 36)');
+        $expected = 16 * 1.5 * 1.5;
+        $this->assertEqualsWithDelta($expected, $result[0]['result'], 1e-12, 'should scale polygon area by factor squared (16 * 1.5^2)');

47-56: Same here: derive expected value and use a slightly looser delta.

Improves readability and reduces precision fragility.

         $result = $this->executeDqlQuery($dql);
-        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 0.000000000000001, 'should scale linestring length by factor (2.828... * 0.5 = 1.414...)');
+        $expected = sqrt(2.0);
+        $this->assertEqualsWithDelta($expected, $result[0]['result'], 1e-12, 'should scale linestring length by factor (2 * sqrt(2) * 0.5 = sqrt(2))');
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 99cd11c and fef6689.

📒 Files selected for processing (5)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CentroidTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IntersectionTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RotateTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ScaleTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SplitTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#0
File: :0-0
Timestamp: 2025-08-24T16:52:32.488Z
Learning: All new features in this repository must include proper test coverage before approval - this ltree implementation demonstrates exemplary test coverage with comprehensive unit tests, integration tests, data providers for edge cases, and validation of all relationships and error conditions.
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ScaleTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CentroidTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IntersectionTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RotateTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SplitTest.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ScaleTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CentroidTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IntersectionTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RotateTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SplitTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ScaleTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CentroidTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IntersectionTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RotateTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SplitTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ScaleTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CentroidTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IntersectionTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RotateTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SplitTest.php
📚 Learning: 2025-08-27T18:19:35.789Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ScaleTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CentroidTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IntersectionTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RotateTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SplitTest.php
📚 Learning: 2025-04-22T00:03:37.733Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IntersectionTest.php
🧬 Code graph analysis (5)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ScaleTest.php (6)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Equals.php (1)
  • ST_Equals (22-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Scale.php (1)
  • ST_Scale (23-32)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CentroidTest.php (6)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Centroid.php (1)
  • ST_Centroid (25-32)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Contains.php (1)
  • ST_Contains (22-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Distance.php (1)
  • ST_Distance (23-31)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Equals.php (1)
  • ST_Equals (22-30)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IntersectionTest.php (5)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Equals.php (1)
  • ST_Equals (22-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Intersection.php (1)
  • ST_Intersection (23-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RotateTest.php (6)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Distance.php (1)
  • ST_Distance (23-31)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Rotate.php (1)
  • ST_Rotate (23-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SplitTest.php (4)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Split.php (1)
  • ST_Split (23-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: sloth
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.14 + Doctrine Lexer 1.2
  • GitHub Check: PHP 8.2 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM latest + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.18 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.1 + Doctrine ORM 2.18 + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.1 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: wait-for-tests-worflows-before-upload
🔇 Additional comments (10)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CentroidTest.php (3)

15-23: Function registration is correct and minimal.

All used DQL functions are registered; no extras. Matches existing patterns in Integration tests.


25-34: Good positive control for point geometries.

Centroid equality for a POINT is the right smoke test.


36-45: Solid containment assertion for polygons.

Using ST_CONTAINS against the polygon’s centroid is appropriate here.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_IntersectionTest.php (2)

14-21: Function registration looks correct and consistent with existing patterns.

Keys match the DQL used below; mappings to ST_Area, ST_Equals, and ST_Intersection are appropriate.


34-43: Implement or verify ST_IsEmpty function before test update
No ST_IsEmpty wrapper was found in Doctrine\ORM\Query\AST\Functions\PostGIS; please add the ST_IsEmpty class and register it in the DQL function map ('ST_ISEMPTY' => ST_IsEmpty::class) before refactoring the test to use ST_ISEMPTY and assertTrue(...).

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_RotateTest.php (1)

15-23: DQL function mapping looks correct.

The registration for ST_AREA, ST_DISTANCE, ST_LENGTH, and ST_ROTATE aligns with usage below.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SplitTest.php (2)

13-19: Correct DQL function mapping.

Mapping ST_LENGTH and ST_SPLIT to their wrappers via getStringFunctions() is consistent with the project’s PostGIS tests.


9-9: No changes needed: PHPUnit 10+ is already configured
composer.json already requires "phpunit/phpunit": "^10.5.53", which supports #[Test] attributes.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ScaleTest.php (2)

7-11: Imports look correct and minimal.

Covers only the DQL functions used in this test plus the attribute import. LGTM.


15-23: Function registration aligns with project patterns.

Uppercase names and class mappings match existing tests and wrappers.

coderabbitai[bot]
coderabbitai bot previously requested changes Sep 3, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (18)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2DTest.php (4)

33-39: Polygon case LGTM (length of non-linear geometries is 0)

Optional: align style with the first test (float cast, small delta) for consistency.


44-49: Point case LGTM

Optional: use assertEqualsWithDelta with float cast for uniformity.


10-50: Add a projected-units check using SRID 3857 fixture (strengthens intent)

You already inserted SRID 3857 test data (id = 10) with a known 2,000 m L-shaped line. Verifying this guards against unit misunderstandings and validates planar behavior on projected CRS.

Apply before the class closing brace:

+    #[Test]
+    public function returns_length_for_linestring_in_projected_units(): void
+    {
+        $dql = 'SELECT ST_LENGTH2D(g.geometry1) as result
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
+                WHERE g.id = 10';
+
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(2000.0, (float) $result[0]["result"], 1.0E-9, 'should return length in projected units (meters in EPSG:3857)');
+    }

22-28: Cast scalar result to float and maintain existing delta

-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.000000000000001, 'should return correct linestring length');
+        $this->assertEqualsWithDelta(2.8284271247461903, (float) $result[0]['result'], 0.000000000000001, 'should return correct linestring length');
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php (3)

37-39: Type-strict zero assertion

Cast to float and use assertSame to avoid accidental string/float mismatches from DBAL.

-        $this->assertEquals(0, $result[0]['result']);
+        $this->assertSame(0.0, (float) $result[0]['result']);

22-25: Minor: extract a helper to DRY the “run-and-pluck” pattern

Optional, but a tiny private helper improves readability across similar tests.

 class ST_FrechetDistanceTest extends SpatialOperatorTestCase
 {
+    /** @return float */
+    private function runAndGet(string $dql): float
+    {
+        $rows = $this->executeDqlQuery($dql);
+        return (float) $rows[0]['result'];
+    }
@@
-        $result = $this->executeDqlQuery($dql);
-        $this->assertEqualsWithDelta(4.242640687119285, $result[0]['result'], 1.0e-12, 'should return correct distance between disjoint linestrings');
+        $this->assertEqualsWithDelta(4.242640687119285, $this->runAndGet($dql), 1.0e-12, 'should return correct distance between disjoint linestrings');
@@
-        $result = $this->executeDqlQuery($dql);
-        $this->assertSame(0.0, (float) $result[0]['result']);
+        $this->assertSame(0.0, $this->runAndGet($dql));
@@
-        $result = $this->executeDqlQuery($dql);
-        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 1.0e-12, 'should return correct distance between overlapping polygons');
+        $this->assertEqualsWithDelta(1.4142135623730951, $this->runAndGet($dql), 1.0e-12, 'should return correct distance between overlapping polygons');

Also applies to: 44-47


26-28: Relax float deltas to match existing tests

Use 1e-6 (already common in this suite) instead of 1e-15 to avoid spurious failures:

@@ tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php:26-28
-        $this->assertEqualsWithDelta(4.242640687119285, $result[0]['result'], 0.000000000000001, 'should return correct distance between disjoint linestrings');
+        $this->assertEqualsWithDelta(4.242640687119285, $result[0]['result'], 1.0e-6, 'should return correct distance between disjoint linestrings');
@@ tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php:48-50
-        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 0.000000000000001, 'should return correct distance between overlapping polygons');
+        $this->assertEqualsWithDelta(1.4142135623730951, $result[0]['result'], 1.0e-6, 'should return correct distance between overlapping polygons');
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnionTest.php (4)

25-34: Stabilize numeric assertion for area

Minor: guard against floating-point differences across PostGIS versions by using a tiny delta and explicit float cast.

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEquals(16, $result[0]['result'], 'should preserve polygon area');
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(16.0, (float) $result[0]['result'], 1e-12, 'should preserve polygon area');

36-45: Avoid magic number and relax delta slightly to reduce CI flakiness

Compute the expectation and use a slightly looser delta; also cast the DB result explicitly.

-        $result = $this->executeDqlQuery($dql);
-        $this->assertEqualsWithDelta(2.8284271247461903, $result[0]['result'], 0.000000000000001, 'should preserve linestring length');
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(2 * \sqrt(2), (float) $result[0]['result'], 1e-12, 'should preserve linestring length');

47-56: Make boolean assertion robust to driver/hydration variations

assertTrue() on a non-empty string (e.g., 'f') would still pass. Coerce the result in SQL and assert strictly.

-        $dql = 'SELECT ST_EQUALS(ST_UNARYUNION(g.geometry1), g.geometry1) as result
+        $dql = 'SELECT CASE WHEN ST_EQUALS(ST_UNARYUNION(g.geometry1), g.geometry1) THEN 1 ELSE 0 END as result
                 FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
                 WHERE g.id = 1';
 
-        $result = $this->executeDqlQuery($dql);
-        $this->assertTrue($result[0]['result'], 'should return unchanged point for point geometries');
+        $result = $this->executeDqlQuery($dql);
+        $this->assertSame(1, (int) $result[0]['result'], 'should return unchanged point for point geometries');

If you prefer to keep the original SQL, assert strictly when the driver hydrates booleans:

$this->assertSame(true, $result[0]['result']);

Please confirm how booleans are hydrated in your current Doctrine/DBAL setup.


25-56: Optional: add a union-through-collection case to exercise topology merging

Consider an extra test that unions adjacent polygons to form a single surface, e.g., with id=8 using ST_Collect(geometry1, geometry2) and asserting area=8 after ST_UnaryUnion. Register ST_COLLECT if available.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifferenceTest.php (2)

45-54: Relax delta and cast for cross-platform stability

PostGIS/GEOS and PDO can introduce tiny representation differences (and Doctrine may return numerics as strings). Casting and a slightly looser epsilon reduces flakiness without weakening the check.

Apply this diff:

-        $this->assertEqualsWithDelta(5.656854249492381, $result[0]['result'], 0.000000000000001, 'should preserve total length of disjoint linestrings');
+        $this->assertEqualsWithDelta(5.656854249492381, (float) $result[0]['result'], 1.0e-12, 'should preserve total length of disjoint linestrings');

23-54: Consider a few extra cases to harden coverage

These are quick wins that exercise edge behavior of ST_SYMDIFFERENCE with your existing fixture rows:

  • Commutativity: swapping args should not change the result (use id=4).
  • Identical polygons: Δ should be empty → area 0 (use id=7).
  • Touching-only (shared edge): no intersection area → union area = 8 (use id=8).

Example additions:

#[Test]
public function returns_zero_for_identical_polygons(): void
{
    $dql = 'SELECT ST_AREA(ST_SYMDIFFERENCE(g.geometry1, g.geometry2)) AS result
            FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
            WHERE g.id = 7';
    $result = $this->executeDqlQuery($dql);
    $this->assertEquals(0.0, (float) $result[0]['result'], 'Δ of identical polygons should be empty (area 0)');
}

#[Test]
public function is_commutative_when_arguments_are_swapped(): void
{
    $dql1 = 'SELECT ST_AREA(ST_SYMDIFFERENCE(g.geometry1, g.geometry2)) AS result
             FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
             WHERE g.id = 4';
    $dql2 = 'SELECT ST_AREA(ST_SYMDIFFERENCE(g.geometry2, g.geometry1)) AS result
             FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
             WHERE g.id = 4';
    $r1 = $this->executeDqlQuery($dql1)[0]['result'];
    $r2 = $this->executeDqlQuery($dql2)[0]['result'];
    $this->assertEqualsWithDelta((float) $r1, (float) $r2, 1.0e-12, 'ST_SYMDIFFERENCE should be commutative');
}

#[Test]
public function returns_union_area_for_edge_touching_polygons(): void
{
    $dql = 'SELECT ST_AREA(ST_SYMDIFFERENCE(g.geometry1, g.geometry2)) AS result
            FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
            WHERE g.id = 8';
    $result = $this->executeDqlQuery($dql);
    $this->assertEquals(8.0, (float) $result[0]['result'], 'Touching-only squares should yield union area (8)');
}
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php (5)

34-43: Consider adding a parameterized variant.

Add one test that uses DQL parameters for distance/azimuth to validate placeholder handling in SimpleArithmeticExpression.

Example to add:

#[Test]
public function projects_point_with_parameters(): void
{
    $dql = 'SELECT ST_EQUALS(ST_PROJECT(g.geometry1, :d, :az), ST_PROJECT(g.geometry1, :d, :az)) as result
            FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
            WHERE g.id = 1';
    $result = $this->executeDqlQuery($dql, ['d' => 750.0, 'az' => 0.523599]);
    $this->assertTrue((bool)$result[0]['result']);
}

46-54: Rename for clarity—no field refs are used.

The method name suggests field-driven arguments, but the test uses literals. Rename for intent clarity.

Apply this diff:

-    public function projects_point_with_field_references(): void
+    public function projects_point_is_deterministic_with_same_parameters(): void

56-65: Minor message tweak.

Grammar nit in the assertion message.

Apply this diff:

-        $this->assertFalse($result[0]['result'], 'geometries with non-zero distance should produce different point');
+        $this->assertFalse($result[0]['result'], 'geometries with non-zero distance should produce a different point');

67-76: Use a delta for exact-zero assertion.

Across PostGIS/GEOS versions, tiny floating errors can occur. Use a small delta.

Apply this diff:

-        $this->assertEquals(0, $result[0]['result']);
+        $this->assertEqualsWithDelta(0.0, $result[0]['result'], 1.0E-9);

12-21: Add a geography case to lock units to meters.

One test with geography ensures ST_Project works on spherical distance and that ST_Distance returns meters.

You can append:

#[Test]
public function projects_geography_in_meters(): void
{
    $dql = 'SELECT ST_DISTANCE(g.geography1, ST_PROJECT(g.geography1, 1000, 0)) as result
            FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsGeometries g
            WHERE g.id = 1';
    $result = $this->executeDqlQuery($dql);
    $this->assertEqualsWithDelta(1000.0, (float)$result[0]['result'], 1.0, 'geography uses meters (1km ± 1m)');
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fef6689 and d35a98b.

📒 Files selected for processing (5)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2DTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifferenceTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnionTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#0
File: :0-0
Timestamp: 2025-08-24T16:52:32.488Z
Learning: All new features in this repository must include proper test coverage before approval - this ltree implementation demonstrates exemplary test coverage with comprehensive unit tests, integration tests, data providers for edge cases, and validation of all relationships and error conditions.
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnionTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifferenceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2DTest.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnionTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifferenceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2DTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnionTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifferenceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2DTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnionTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifferenceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2DTest.php
📚 Learning: 2025-08-27T18:19:35.789Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#430
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/StrictlyRightTest.php:31-36
Timestamp: 2025-08-27T18:19:35.789Z
Learning: WKT string literals can be used directly in Doctrine spatial function tests (e.g., 'POINT(-5 -5)') without explicit ST_GeomFromText wrapping, as PostgreSQL/PostGIS automatically handles the implicit conversion to geometry types when used with spatial operators.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnionTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifferenceTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2DTest.php
📚 Learning: 2025-04-22T00:03:37.733Z
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.

Applied to files:

  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php
🧬 Code graph analysis (5)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnionTest.php (6)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Equals.php (1)
  • ST_Equals (22-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnion.php (1)
  • ST_UnaryUnion (23-30)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistance.php (1)
  • ST_FrechetDistance (23-31)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php (5)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Distance.php (1)
  • ST_Distance (23-31)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Equals.php (1)
  • ST_Equals (22-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Project.php (1)
  • ST_Project (23-32)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifferenceTest.php (5)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Area.php (1)
  • ST_Area (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length.php (1)
  • ST_Length (23-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifference.php (1)
  • ST_SymDifference (23-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2DTest.php (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2D.php (1)
  • ST_Length2D (23-30)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/SpatialOperatorTestCase.php (1)
  • SpatialOperatorTestCase (9-120)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (271-285)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.4
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.4
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.2
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.1
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.18 + Doctrine Lexer 3.0
  • GitHub Check: sloth
  • GitHub Check: wait-for-tests-worflows-before-upload
🔇 Additional comments (7)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_Length2DTest.php (1)

12-17: Function registration looks correct

Alias and class mapping follow the established pattern and should enable the DQL function as intended.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_FrechetDistanceTest.php (1)

12-17: Function registration looks correct

Alias matches wrapper name and follows existing patterns.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_UnaryUnionTest.php (1)

15-23: Function registrations look correct and consistent

Mappings match project conventions and cover only what's used in this test. LGTM.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_SymDifferenceTest.php (3)

14-21: Function registration looks correct

Keys match the expected uppercase naming and mirror existing patterns; wrappers are mapped appropriately for the DQL engine.


23-32: Polygon Δ test: solid and numerically sound

Area(4×4) + Area(2×2) − 2×Area(2×2) = 12 checks out for id=2 (inner fully contained). Good choice to assert via ST_AREA.


34-43: Overlap Δ test: correct

For two 2×2 squares overlapping on a 1×1, 4 + 4 − 2×1 = 6 is correct. Assertion is crisp.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_ProjectTest.php (1)

14-21: Function registration looks correct and scoped.

Good use of StringPrimary/SimpleArithmeticExpression and registering only what the test needs.

@martin-georgiev martin-georgiev marked this pull request as ready for review September 3, 2025 22:21
@martin-georgiev martin-georgiev dismissed coderabbitai[bot]’s stale review September 3, 2025 22:21

largely misleading comments

@martin-georgiev martin-georgiev merged commit 9724452 into main Sep 3, 2025
68 of 69 checks passed
@martin-georgiev martin-georgiev deleted the new-postgis-functions-2 branch September 3, 2025 22:24
@github-actions github-actions bot mentioned this pull request Sep 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants