Skip to content

Conversation

@ddegasperi
Copy link

@ddegasperi ddegasperi commented Aug 18, 2025

Q A
Type feature
Fixed issues #7081

Summary

This PR introduces spatial data type support for DBAL, starting with PostgreSQL/PostGIS and MySQL. This implementation is intended to serve as a reference and guide for adding support for other database platforms in the future.

Core Spatial Types

  • GeometryType (Types::GEOMETRY) - For planar coordinate systems
  • GeographyType (Types::GEOGRAPHY) - For spherical earth coordinates
  • Both types handle GeoJSON format for data exchange

Schema API Integration

  • Extended Column and ColumnEditor with geometryType and srid properties
  • Clean fluent API: Column::editor()->setGeometryType('POINT')->setSrid(4326)
  • Full PostgreSQL platform support with PostGIS-specific SQL generation
  • Schema introspection and table creation/modification support

What's next

  • Discuss the PR
  • Add other platforms (PostgreSQL/PostGIS, MySQL)
  • Add spatial index (PostgreSQL/PostGIS, MySQL already support creation of spatial indexes)

Comment on lines +1091 to +1109
self::assertSame(
[
'CREATE TABLE spatial_table (id INT NOT NULL, '
. 'location geometry(geometry) NOT NULL, '
. 'point_location geometry(point,4326) NOT NULL, '
. 'polygon_area geometry(polygon) NOT NULL)',
],
$this->platform->getCreateTableSQL($table),
);
Copy link
Member

Choose a reason for hiding this comment

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

Please focus on functional tests. The kind of test that you're building here is pretty much worthless because it does not tell us if the SQL actually works when it hits a database.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for the feedback! I already had in mind to add functional tests, since they’re definitely the right way to validate the SQL.
Because these tests require PostgreSQL with the PostGIS extension, would you suggest:

  • creating a dedicated GitHub workflow (e.g. postgresql-postgis.yml) that uses the postgis/postgis image, or
  • replacing the current PostgreSQL workflow with that image so that all PostgreSQL jobs run with PostGIS enabled?

I’d be happy to go with whichever approach best fits the project’s CI strategy.

Copy link
Member

Choose a reason for hiding this comment

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

We need to make sure DBAL still works with Postgres databases that don't have these extensions installed. So it's probably best for now if we add an additional check for Postgres that uses the latest postgis image and leave the other checks as they are.

Copy link
Author

Choose a reason for hiding this comment

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

@derrabus I’ve added the functional tests as suggested and pushed them. However, I noticed that none of the functional tests actually executed in the PR pipeline — is there something I need to do to make sure they run?

If you already had a chance to take a look, I’d really appreciate some feedback on whether this is heading in the right direction. That way I can adjust before proceeding with support for a second platform (e.g. MySQL).

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

Yes, I noticed an error in continuous-integration.yml only afterwards. After fixing it, the functional tests were executed correctly.

I have one question regarding the functional tests: in MySQL there is a test case Doctrine\DBAL\Tests\Functional\Schema\MySQLSchemaManagerTest::testColumnIntrospection that attempts to define any type as a column to compare it against the same definition. At the moment, I’ve introduced two types for PostgreSQL/PostGIS, geometry and geography. Since geography is not available in MySQL, the current test setup would fail.

Is this behavior intentional, or would it be acceptable to adjust the tests so that they explicitly check which types are supported on MySQL?

@greg0ire greg0ire marked this pull request as draft August 26, 2025 14:16
@ddegasperi ddegasperi force-pushed the add-spatial-types branch 3 times, most recently from 810f526 to 86b4b15 Compare August 28, 2025 06:44
Comment on lines 53 to 55
if (is_string($value)) {
return $value;
}
Copy link
Member

Choose a reason for hiding this comment

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

Is there any object representation that we could hydrate this value to? If we just pass on the strings we might end up with a leaky abstraction.

Copy link
Author

Choose a reason for hiding this comment

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

Good point — I agree that passing raw strings would be a leaky abstraction. Since the implementation uses WKT, I could introduce a lightweight WKT value object that wraps and optionally validates the string (e.g. via regexp). This would give us a clear object representation without pulling in a full geometry library. Would this be in line with what you had in mind?

Copy link
Author

Choose a reason for hiding this comment

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

I decided not to introduce a WKT value object and went with a GeoJSON value object instead. GeoJSON provides both the geometry and its metadata (such as SRID) in a consistent way across different database platforms.

@tibobaldwin
Copy link

tibobaldwin commented Sep 6, 2025

Adding spatial index management would be interesting for this PR I think :).

For instance:
CREATE INDEX mytable_geom_x ON mytable USING GIST (geom)

Sources:

@ddegasperi
Copy link
Author

Adding spatial index management would be interesting

Thanks for the advice — I agree, index management is definitely an important aspect when working with geometry data. I haven’t investigated it in depth yet, but it looks like this might already be supported by specifying the index type. A quick search in the repository shows an IndexType enum with a SPATIAL option, so I’ll take a closer look at how that could be integrated here.

@ddegasperi ddegasperi force-pushed the add-spatial-types branch 2 times, most recently from ba2a7aa to a33fcd8 Compare October 10, 2025 13:06
@ddegasperi ddegasperi force-pushed the add-spatial-types branch 3 times, most recently from 21795c6 to bc5c9db Compare October 14, 2025 14:43
Add geometry and geography types for spatial data

Introduces new spatial data types for handling geometric and geographic data in database applications. GeometryType handles planar coordinates while GeographyType handles spherical earth coordinates, both using GeoJSON format.

This provides foundation for spatial data operations across database platforms that support spatial extensions.
Extends Column and ColumnEditor with geometryType and srid properties to support PostgreSQL's PostGIS spatial types and provides a clean schema API for working with GEOMETRY and GEOGRAPHY columns while maintaining backward compatibility.

This builds on the core spatial types implementation to complete the PostgreSQL spatial type support at the schema level.
This commit adds functional testing for PostGIS spatial types (GEOMETRY and GEOGRAPHY) with schema introspection and CI integration.

The implementation leverages PostgreSQL's native type system for introspection, making it compatible with any PostgreSQL instance without requiring PostGIS system tables to be accessible during schema operations.
Extends AbstractMySQLPlatform with GEOMETRY type support and enhances MySQLSchemaManager to introspect spatial columns with geometryType and SRID properties.

MySQL supports GEOMETRY types (POINT, LINESTRING, POLYGON, etc.) with optional SRID constraints using the conditional comment syntax for MySQL 8.0.3+.
Refactor GeometryType and GeographyType to replace direct GeoJSON string handling with dedicated value objects, preventing exposure of database-specific formats to application code.

This commit introduces a Geometry value object that encapsulates a supporting GeoJSON value object responsible for validating and wrapping GeoJSON representations.
Implement spatial index creation and introspection for PostgreSQL using the GIST (Generalized Search Tree) index method — the standard access method for spatial data in PostGIS.
This commit introduces a new getIndexMethodSQL() hook in AbstractPlatform for platform-specific index clauses, and overrides it in PostgreSQLPlatform to emit "USING GIST" for spatial indexes.

SQL generation examples:
MySQL → CREATE SPATIAL INDEX idx ON table (col)
PostgreSQL → CREATE INDEX idx ON table USING GIST (col)
@ddegasperi ddegasperi changed the title [DRAFT] Add spatial types Add spatial types Oct 14, 2025
@ddegasperi ddegasperi marked this pull request as ready for review October 14, 2025 15:25
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