Skip to content

Commit 543f582

Browse files
committed
Add PostgreSQL spatial type support
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.
1 parent 7d710a1 commit 543f582

File tree

6 files changed

+326
-19
lines changed

6 files changed

+326
-19
lines changed

src/Platforms/PostgreSQLPlatform.php

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace Doctrine\DBAL\Platforms;
66

77
use Doctrine\DBAL\Connection;
8-
use Doctrine\DBAL\Platforms\Exception\NotSupported;
98
use Doctrine\DBAL\Platforms\Keywords\KeywordList;
109
use Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords;
1110
use Doctrine\DBAL\Schema\Column;
@@ -728,6 +727,8 @@ protected function initializeDoctrineTypeMappings(): void
728727
'float' => Types::FLOAT,
729728
'float4' => Types::SMALLFLOAT,
730729
'float8' => Types::FLOAT,
730+
'geography' => Types::GEOGRAPHY,
731+
'geometry' => Types::GEOMETRY,
731732
'inet' => Types::STRING,
732733
'int' => Types::INTEGER,
733734
'int2' => Types::SMALLINT,
@@ -828,35 +829,41 @@ public function getJsonbTypeDeclarationSQL(array $column): string
828829
*/
829830
public function getGeometryTypeDeclarationSQL(array $column): string
830831
{
831-
throw NotSupported::new(__METHOD__);
832+
$geometryType = $column['geometryType'] ?? 'geometry';
833+
$srid = $column['srid'] ?? null;
834+
835+
return sprintf('geometry(%s%s)', strtolower($geometryType), $srid !== null ? ',' . $srid : '');
832836
}
833837

834838
public function getGeometryFromTextSQL(string $sqlExpr): string
835839
{
836-
throw NotSupported::new(__METHOD__);
840+
return sprintf('ST_GeomFromEWKT(%s)', $sqlExpr);
837841
}
838842

839843
public function getGeometryAsTextSQL(string $sqlExpr): string
840844
{
841-
throw NotSupported::new(__METHOD__);
845+
return sprintf('ST_AsEWKT(%s)', $sqlExpr);
842846
}
843847

844848
/**
845849
* {@inheritDoc}
846850
*/
847851
public function getGeographyTypeDeclarationSQL(array $column): string
848852
{
849-
throw NotSupported::new(__METHOD__);
853+
$geometryType = $column['geometryType'] ?? 'geometry';
854+
$srid = $column['srid'] ?? null;
855+
856+
return sprintf('geography(%s%s)', strtolower($geometryType), $srid !== null ? ',' . $srid : '');
850857
}
851858

852859
public function getGeographyFromTextSQL(string $sqlExpr): string
853860
{
854-
throw NotSupported::new(__METHOD__);
861+
return sprintf('ST_GeogFromText(%s)', $sqlExpr);
855862
}
856863

857864
public function getGeographyAsTextSQL(string $sqlExpr): string
858865
{
859-
throw NotSupported::new(__METHOD__);
866+
return sprintf('ST_AsEWKT(%s)', $sqlExpr);
860867
}
861868

862869
public function createSchemaManager(Connection $connection): PostgreSQLSchemaManager

src/Schema/Column.php

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,17 @@
3030
* comment: string,
3131
* charset?: ?non-empty-string,
3232
* collation?: ?non-empty-string,
33+
* geometryType?: ?non-empty-string,
34+
* srid?: ?int,
3335
* }
3436
* @phpstan-type PlatformOptions = array{
3537
* charset?: ?non-empty-string,
3638
* collation?: ?non-empty-string,
3739
* default_constraint_name?: non-empty-string,
3840
* jsonb?: bool,
3941
* version?: bool,
42+
* geometryType?: ?non-empty-string,
43+
* srid?: ?int,
4044
* }
4145
*/
4246
class Column extends AbstractNamedObject
@@ -290,8 +294,26 @@ public function getDefaultConstraintName(): ?string
290294
}
291295

292296
/**
293-
* @deprecated Use {@see getCharset()}, {@see getCollation()}, {@see getMinimumValue()} or {@see getMaximumValue()}
294-
* instead.
297+
* Returns the geometry type for spatial columns.
298+
*
299+
* @return ?non-empty-string
300+
*/
301+
public function getGeometryType(): ?string
302+
{
303+
return $this->_platformOptions['geometryType'] ?? null;
304+
}
305+
306+
/**
307+
* Returns the SRID (Spatial Reference System Identifier) for spatial columns.
308+
*/
309+
public function getSrid(): ?int
310+
{
311+
return $this->_platformOptions['srid'] ?? null;
312+
}
313+
314+
/**
315+
* @deprecated Use {@see getCharset()}, {@see getCollation()}, {@see getMinimumValue()}, {@see getMaximumValue()},
316+
* {@see getGeometryType()} or {@see getSrid()} instead.
295317
*
296318
* @return PlatformOptions
297319
*/
@@ -301,8 +323,8 @@ public function getPlatformOptions(): array
301323
}
302324

303325
/**
304-
* @deprecated Use {@see getCharset()}, {@see getCollation()}, {@see getMinimumValue()} or {@see getMaximumValue()}
305-
* instead.
326+
* @deprecated Use {@see getCharset()}, {@see getCollation()}, {@see getMinimumValue()}, {@see getMaximumValue()},
327+
* {@see getGeometryType()} or {@see getSrid()} instead.
306328
*
307329
* @param key-of<PlatformOptions> $name
308330
*/
@@ -312,8 +334,8 @@ public function hasPlatformOption(string $name): bool
312334
}
313335

314336
/**
315-
* @deprecated Use {@see getCharset()}, {@see getCollation()}, {@see getMinimumValue()} or {@see getMaximumValue()}
316-
* instead.
337+
* @deprecated Use {@see getCharset()}, {@see getCollation()}, {@see getMinimumValue()}, {@see getMaximumValue()},
338+
* {@see getGeometryType()} or {@see getSrid()} instead.
317339
*
318340
* @param key-of<PlatformOptions> $name
319341
*/
@@ -415,6 +437,8 @@ public function edit(): ColumnEditor
415437
->setCollation($this->getCollation())
416438
->setMinimumValue($this->getMinimumValue())
417439
->setMaximumValue($this->getMaximumValue())
418-
->setDefaultConstraintName($this->getDefaultConstraintName());
440+
->setDefaultConstraintName($this->getDefaultConstraintName())
441+
->setGeometryType($this->getGeometryType())
442+
->setSrid($this->getSrid());
419443
}
420444
}

src/Schema/ColumnEditor.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ final class ColumnEditor
5353
/** @var ?non-empty-string */
5454
private ?string $columnDefinition = null;
5555

56+
/** @var ?non-empty-string */
57+
private ?string $geometryType = null;
58+
59+
private ?int $srid = null;
60+
5661
/** @internal Use {@link Column::editor()} or {@link Column::edit()} to create an instance */
5762
public function __construct()
5863
{
@@ -217,6 +222,21 @@ public function setColumnDefinition(?string $columnDefinition): self
217222
return $this;
218223
}
219224

225+
/** @param ?non-empty-string $geometryType */
226+
public function setGeometryType(?string $geometryType): self
227+
{
228+
$this->geometryType = $geometryType;
229+
230+
return $this;
231+
}
232+
233+
public function setSrid(?int $srid): self
234+
{
235+
$this->srid = $srid;
236+
237+
return $this;
238+
}
239+
220240
public function create(): Column
221241
{
222242
if ($this->name === null) {
@@ -249,6 +269,14 @@ public function create(): Column
249269
$platformOptions[SQLServerPlatform::OPTION_DEFAULT_CONSTRAINT_NAME] = $this->defaultConstraintName;
250270
}
251271

272+
if ($this->geometryType !== null) {
273+
$platformOptions['geometryType'] = $this->geometryType;
274+
}
275+
276+
if ($this->srid !== null) {
277+
$platformOptions['srid'] = $this->srid;
278+
}
279+
252280
return new Column(
253281
$this->name->toString(),
254282
$this->type,

src/Schema/PostgreSQLSchemaManager.php

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,13 @@ protected function _getPortableTableColumnDefinition(array $tableColumn): Column
208208
{
209209
$tableColumn = array_change_key_case($tableColumn, CASE_LOWER);
210210

211-
$length = null;
212-
$precision = null;
213-
$scale = 0;
214-
$fixed = false;
215-
$jsonb = false;
211+
$length = null;
212+
$precision = null;
213+
$scale = 0;
214+
$fixed = false;
215+
$jsonb = false;
216+
$geometryType = null;
217+
$srid = null;
216218

217219
$dbType = $tableColumn['type'];
218220

@@ -251,6 +253,18 @@ protected function _getPortableTableColumnDefinition(array $tableColumn): Column
251253
$scale = $parameters[1];
252254
}
253255

256+
break;
257+
case 'geometry':
258+
case 'geography':
259+
$parameters = $this->parseColumnTypeParameters($completeType);
260+
if (count($parameters) > 0) {
261+
$geometryType = $parameters[0];
262+
}
263+
264+
if (count($parameters) > 1) {
265+
$srid = $parameters[1];
266+
}
267+
254268
break;
255269
}
256270

@@ -280,6 +294,14 @@ protected function _getPortableTableColumnDefinition(array $tableColumn): Column
280294
$column->setPlatformOption('collation', $tableColumn['collation']);
281295
}
282296

297+
if ($geometryType !== null) {
298+
$column->setPlatformOption('geometryType', $geometryType);
299+
}
300+
301+
if ($srid !== null) {
302+
$column->setPlatformOption('srid', $srid);
303+
}
304+
283305
if ($column->getType() instanceof JsonType) {
284306
$column->setPlatformOption('jsonb', $jsonb);
285307
}

0 commit comments

Comments
 (0)