Skip to content

Commit

Permalink
Merge pull request #138 from nhibernate/feature/postgis-3
Browse files Browse the repository at this point in the history
Add spatial dialect for PostGIS 3.0+
  • Loading branch information
peetw authored Jan 21, 2024
2 parents f8024d5 + 9d73ede commit 17d980e
Show file tree
Hide file tree
Showing 19 changed files with 310 additions and 9 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ jobs:
DB_INIT: docker run -d -e POSTGRES_PASSWORD=nhsp_test -p 15432:5432 -v ./Tests.NHibernate.Spatial.PostGis20/initdb:/docker-entrypoint-initdb.d postgis/postgis:12-2.5
TEST_PROJECT: Tests.NHibernate.Spatial.PostGis20

- DB: PostGis20 (PostgreSQL 12 PostGIS 3.4)
DB_INIT: docker run -d -e POSTGRES_PASSWORD=nhsp_test -p 15432:5432 -v ./Tests.NHibernate.Spatial.PostGis20/initdb:/docker-entrypoint-initdb.d postgis/postgis:12-3.4
TEST_PROJECT: Tests.NHibernate.Spatial.PostGis20
- DB: PostGis30 (PostgreSQL 12 PostGIS 3.0)
DB_INIT: docker run -d -e POSTGRES_PASSWORD=nhsp_test -p 15433:5432 -v ./Tests.NHibernate.Spatial.PostGis30/initdb:/docker-entrypoint-initdb.d postgis/postgis:12-3.0
TEST_PROJECT: Tests.NHibernate.Spatial.PostGis30

- DB: PostGis20 (PostgreSQL 16 PostGIS 3.4)
DB_INIT: docker run -d -e POSTGRES_PASSWORD=nhsp_test -p 15432:5432 -v ./Tests.NHibernate.Spatial.PostGis20/initdb:/docker-entrypoint-initdb.d postgis/postgis:16-3.4
TEST_PROJECT: Tests.NHibernate.Spatial.PostGis20
- DB: PostGis30 (PostgreSQL 16 PostGIS 3.4)
DB_INIT: docker run -d -e POSTGRES_PASSWORD=nhsp_test -p 15433:5432 -v ./Tests.NHibernate.Spatial.PostGis30/initdb:/docker-entrypoint-initdb.d postgis/postgis:16-3.4
TEST_PROJECT: Tests.NHibernate.Spatial.PostGis30

steps:
- name: Checkout repository
Expand Down
4 changes: 2 additions & 2 deletions NHibernate.Spatial.PostGis/Dialect/PostGis20Dialect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ public SqlString GetSpatialAggregateString(object geometry, SpatialAggregate agg
return builder.ToSqlString();
}

public SqlString GetSpatialRelationString(object geometry, SpatialRelation relation, object anotherGeometry, bool criterion)
public virtual SqlString GetSpatialRelationString(object geometry, SpatialRelation relation, object anotherGeometry, bool criterion)
{
switch (relation)
{
Expand Down Expand Up @@ -428,7 +428,7 @@ public SqlString GetSpatialFilterString(string tableAlias, string geometryColumn
/// <param name="analysis">The analysis.</param>
/// <param name="extraArgument">The extra argument.</param>
/// <returns></returns>
public SqlString GetSpatialAnalysisString(object geometry, SpatialAnalysis analysis, object extraArgument)
public virtual SqlString GetSpatialAnalysisString(object geometry, SpatialAnalysis analysis, object extraArgument)
{
switch (analysis)
{
Expand Down
68 changes: 68 additions & 0 deletions NHibernate.Spatial.PostGis/Dialect/PostGis30Dialect.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using NHibernate.SqlCommand;
using System;

namespace NHibernate.Spatial.Dialect
{
/// <summary>
///
/// </summary>
public class PostGis30Dialect : PostGis20Dialect
{
public override SqlString GetSpatialRelationString(object geometry, SpatialRelation relation, object anotherGeometry, bool criterion)
{
switch (relation)
{
case SpatialRelation.Covers:
case SpatialRelation.CoveredBy:
case SpatialRelation.EqualsExact:
return base.GetSpatialRelationString(geometry, relation, anotherGeometry, criterion);

default:
return new SqlStringBuilder(6)
.Add(SpatialDialect.IsoPrefix)
.Add(relation.ToString())
.Add("(")
.AddObject(geometry)
.Add(", ")
.AddObject(anotherGeometry)
.Add(")")
.ToSqlString();
}
}

/// <summary>
/// Gets the spatial analysis string.
/// </summary>
/// <param name="geometry">The geometry.</param>
/// <param name="analysis">The analysis.</param>
/// <param name="extraArgument">The extra argument.</param>
/// <returns></returns>
public override SqlString GetSpatialAnalysisString(object geometry, SpatialAnalysis analysis, object extraArgument)
{
switch (analysis)
{
case SpatialAnalysis.Buffer:
case SpatialAnalysis.ConvexHull:
return base.GetSpatialAnalysisString(geometry, analysis, extraArgument);

case SpatialAnalysis.Difference:
case SpatialAnalysis.Distance:
case SpatialAnalysis.Intersection:
case SpatialAnalysis.SymDifference:
case SpatialAnalysis.Union:
return new SqlStringBuilder()
.Add(SpatialDialect.IsoPrefix)
.Add(analysis.ToString())
.Add("(")
.AddObject(geometry)
.Add(",")
.AddObject(extraArgument)
.Add(")")
.ToSqlString();

default:
throw new ArgumentException("Invalid spatial analysis argument");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">

<class name="NHibernate.Spatial.Metadata.GeometryColumn, NHibernate.Spatial"
schema="public"
table="GEOMETRY_COLUMNS"
lazy="false"
mutable="false">
<composite-id>
<key-property name="TableCatalog" column="F_TABLE_CATALOG" />
<key-property name="TableSchema" column="F_TABLE_SCHEMA" />
<key-property name="TableName" column="F_TABLE_NAME" />
<key-property name="Name" column="F_GEOMETRY_COLUMN" />
</composite-id>
<property name="SRID" column="SRID" />
<property name="Subtype" column="TYPE" />
<property name="Dimension" column="COORD_DIMENSION" />
</class>
</hibernate-mapping>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">

<class name="NHibernate.Spatial.Metadata.SpatialReferenceSystem, NHibernate.Spatial"
schema="public"
table="SPATIAL_REF_SYS"
lazy="false"
mutable="true">
<id name="SRID" column="SRID" type="Int32">
<generator class="assigned" />
</id>
<property name="AuthorityName" column="AUTH_NAME" type="String" />
<property name="AuthoritySRID" column="AUTH_SRID" type="Int32" />
<property name="WellKnownText" column="SRTEXT" type="String" />
</class>
</hibernate-mapping>
4 changes: 4 additions & 0 deletions NHibernate.Spatial.PostGis/NHibernate.Spatial.PostGis.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@

<ItemGroup>
<None Remove="Metadata\GeometryColumn.PostGis20Dialect.hbm.xml" />
<None Remove="Metadata\GeometryColumn.PostGis30Dialect.hbm.xml" />
<None Remove="Metadata\SpatialReferenceSystem.PostGis20Dialect.hbm.xml" />
<None Remove="Metadata\SpatialReferenceSystem.PostGis30Dialect.hbm.xml" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Metadata\GeometryColumn.PostGis30Dialect.hbm.xml" />
<EmbeddedResource Include="Metadata\GeometryColumn.PostGis20Dialect.hbm.xml" />
<EmbeddedResource Include="Metadata\SpatialReferenceSystem.PostGis30Dialect.hbm.xml" />
<EmbeddedResource Include="Metadata\SpatialReferenceSystem.PostGis20Dialect.hbm.xml" />
</ItemGroup>

Expand Down
6 changes: 6 additions & 0 deletions NHibernate.Spatial.sln
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.NHibernate.Spatial.MySQL80", "Tests.NHibernate.Spatial.MySQL80\Tests.NHibernate.Spatial.MySQL80.csproj", "{D6643E3E-D004-41A7-B1AB-96D52018FE17}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.NHibernate.Spatial.PostGis30", "Tests.NHibernate.Spatial.PostGis30\Tests.NHibernate.Spatial.PostGis30.csproj", "{ED1D3C35-D6F7-44CD-88A6-8E9192F685A8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -74,6 +76,10 @@ Global
{D6643E3E-D004-41A7-B1AB-96D52018FE17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6643E3E-D004-41A7-B1AB-96D52018FE17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6643E3E-D004-41A7-B1AB-96D52018FE17}.Release|Any CPU.Build.0 = Release|Any CPU
{ED1D3C35-D6F7-44CD-88A6-8E9192F685A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED1D3C35-D6F7-44CD-88A6-8E9192F685A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED1D3C35-D6F7-44CD-88A6-8E9192F685A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED1D3C35-D6F7-44CD-88A6-8E9192F685A8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Tests.NHibernate.Spatial
public class PostGis20ConformanceItemsFixture : ConformanceItemsFixture
{
/// <summary>
/// Overridden because GeometryType includes ISO prefix in PostGIS 2
/// Overridden because GeometryType includes ISO prefix in PostGIS
/// </summary>
[Test]
public override void ConformanceItemT07Hql()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using NHibernate.Cfg;
using NUnit.Framework;

namespace Tests.NHibernate.Spatial
{
[TestFixture]
public class PostGis30ConformanceItemsFixture : PostGis20ConformanceItemsFixture
{
protected override void Configure(Configuration configuration)
{
TestConfiguration.Configure(configuration);
}
}
}
14 changes: 14 additions & 0 deletions Tests.NHibernate.Spatial.PostGis30/PostGis30CriteriaFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using NHibernate.Cfg;
using NUnit.Framework;

namespace Tests.NHibernate.Spatial
{
[TestFixture]
public class PostGis30CriteriaFixture : CriteriaFixture
{
protected override void Configure(Configuration configuration)
{
TestConfiguration.Configure(configuration);
}
}
}
14 changes: 14 additions & 0 deletions Tests.NHibernate.Spatial.PostGis30/PostGis30MiscTestsFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using NHibernate.Cfg;
using NUnit.Framework;

namespace Tests.NHibernate.Spatial
{
[TestFixture]
public class PostGis30MiscTestsFixture : PostGis20MiscTestsFixture
{
protected override void Configure(Configuration config)
{
TestConfiguration.Configure(config);
}
}
}
15 changes: 15 additions & 0 deletions Tests.NHibernate.Spatial.PostGis30/PostGis30NtsTestCasesFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using NHibernate.Cfg;
using NUnit.Framework;
using Tests.NHibernate.Spatial.NtsTestCases;

namespace Tests.NHibernate.Spatial
{
[TestFixture]
public class PostGis30NtsTestCasesFixture : NtsTestCasesFixture
{
protected override void Configure(Configuration configuration)
{
TestConfiguration.Configure(configuration);
}
}
}
14 changes: 14 additions & 0 deletions Tests.NHibernate.Spatial.PostGis30/PostGis30ProjectionsFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using NHibernate.Cfg;
using NUnit.Framework;

namespace Tests.NHibernate.Spatial
{
[TestFixture]
public class PostGis30ProjectionsFixture : PostGis20ProjectionsFixture
{
protected override void Configure(Configuration configuration)
{
TestConfiguration.Configure(configuration);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using NHibernate.Cfg;
using NUnit.Framework;

namespace Tests.NHibernate.Spatial
{
[TestFixture]
public class PostGis30SpatialQueriesFixture : PostGis20SpatialQueriesFixture
{
protected override void Configure(Configuration configuration)
{
TestConfiguration.Configure(configuration);
}
}
}
39 changes: 39 additions & 0 deletions Tests.NHibernate.Spatial.PostGis30/TestConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Microsoft.Extensions.Configuration;
using NHibernate.Bytecode;
using NHibernate.Cfg;
using NHibernate.Driver;
using NHibernate.Spatial.Dialect;
using Npgsql;
using System.Collections.Generic;

namespace Tests.NHibernate.Spatial
{
internal static class TestConfiguration
{
private static readonly IConfigurationRoot _configurationRoot;

static TestConfiguration()
{
_configurationRoot = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
}

public static void Configure(Configuration configuration)
{
IDictionary<string, string> properties = new Dictionary<string, string>
{
[Environment.ProxyFactoryFactoryClass] = typeof(StaticProxyFactoryFactory).AssemblyQualifiedName,
[Environment.Dialect] = typeof(PostGis30Dialect).AssemblyQualifiedName,
[Environment.ConnectionProvider] = typeof(DebugConnectionProvider).AssemblyQualifiedName,
[Environment.ConnectionDriver] = typeof(NpgsqlDriver).AssemblyQualifiedName,
[Environment.ConnectionString] = _configurationRoot.GetConnectionString("PostGis30")
};
configuration.SetProperties(properties);

// Use NTS plugin for mapping PostGIS types; see:
// https://www.npgsql.org/doc/release-notes/4.0.html#improved-spatial-support-postgis
NpgsqlConnection.GlobalTypeMapper.UseNetTopologySuite();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>

<IsPackable>false</IsPackable>

<RootNamespace>Tests.NHibernate.Spatial</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="nunit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="[3.15.1, 3.16.0)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="[15.9.2, 16.0)" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\NHibernate.Spatial.PostGis\NHibernate.Spatial.PostGis.csproj" />
<ProjectReference Include="..\Tests.NHibernate.Spatial.PostGis20\Tests.NHibernate.Spatial.PostGis20.csproj" />
<ProjectReference Include="..\Tests.NHibernate.Spatial\Tests.NHibernate.Spatial.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
5 changes: 5 additions & 0 deletions Tests.NHibernate.Spatial.PostGis30/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"ConnectionStrings": {
"PostGis30": "Server=localhost;Port=15433;Database=nhsp_test;User Id=nhsp_test;Password=nhsp_test;"
}
}
19 changes: 19 additions & 0 deletions Tests.NHibernate.Spatial.PostGis30/initdb/nhsp_test.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* NHibernate.Spatial PostGIS 3 Test Database Creation Script */

-- Run this script as superuser using psql , i.e.:
-- psql -h localhost -p 5432 -U postgres -f path-to-this-file.sql

CREATE ROLE nhsp_test LOGIN
PASSWORD 'nhsp_test'
NOSUPERUSER NOINHERIT CREATEDB CREATEROLE;

CREATE DATABASE nhsp_test
WITH OWNER = nhsp_test
ENCODING = 'UTF8';

\connect nhsp_test

CREATE EXTENSION postgis;

ALTER TABLE public.geometry_columns OWNER TO nhsp_test;
ALTER TABLE public.spatial_ref_sys OWNER TO nhsp_test;
9 changes: 9 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,12 @@ services:
- 15432:5432
volumes:
- ./Tests.NHibernate.Spatial.PostGis20/initdb:/docker-entrypoint-initdb.d

postgis30:
image: postgis/postgis:12-3.0
environment:
POSTGRES_PASSWORD: # See .env file
ports:
- 15433:5432
volumes:
- ./Tests.NHibernate.Spatial.PostGis30/initdb:/docker-entrypoint-initdb.d

0 comments on commit 17d980e

Please sign in to comment.