Skip to content

Commit

Permalink
HHH-14454 Add SpatialDialect for CockroachDB
Browse files Browse the repository at this point in the history
  • Loading branch information
maesenka committed Mar 16, 2021
1 parent 2c39bc0 commit aba49ce
Show file tree
Hide file tree
Showing 26 changed files with 629 additions and 62 deletions.
Expand Up @@ -86,42 +86,42 @@ relevant section.
:no: icon:times[role="red"]
[[spatial-configuration-dialect-features]]
.Hibernate Spatial dialect function support
[cols=",,,,,,," |options="header",]
[cols=",,,,,,,," |options="header",]
|================================
|Function | Description | PostgresSQL | Oracle 10g/11g | MySQL | SQLServer | GeoDB (H2) | DB2
|Basic functions on Geometry | | | | | | |
|`int dimension(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`String geometrytype(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`int srid(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`Geometry envelope(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`String astext(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`byte[] asbinary(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean isempty(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean issimple(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`Geometry boundary(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}
|Functions for testing Spatial Relations between geometric objects | | | | | | |
|`boolean equals(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean disjoint(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean intersects(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean touches(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean crosses(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean within(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean contains(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean overlaps(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean relate(Geometry, Geometry, String)` | SFS §2.1.1.2 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}
|Functions that support Spatial Analysis | | | | | | |
|`double distance(Geometry, Geometry)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}
|`Geometry buffer(Geometry, double)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}
|`Geometry convexhull(Geometry)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}^(1)^
|`Geometry intersection(Geometry, Geometry)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}^(1)^
|`Geometry geomunion(Geometry, Geometry)` | SFS §2.1.1.3 (renamed from union) | {yes} | {yes} | {no} | {yes} | {yes} | {yes}^(1)^
|`Geometry difference(Geometry, Geometry)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}^(1)^
|`Geometry symdifference(Geometry, Geometry)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}^(1)^
|Common non-SFS functions | | | | | | |
|`boolean dwithin(Geometry, Geometry, double)` | Returns true if the geometries are within the specified distance of one another | {yes} | {yes} | {no} | {no} | {yes} | {yes}
|`Geometry transform(Geometry, int)` | Returns a new geometry with its coordinates transformed to the SRID referenced by the integer parameter | {yes} | {yes} | {no} | {no} | {no} | {no}
|Spatial aggregate Functions | | | | | | |
|`Geometry extent(Geometry)` | Returns a bounding box that bounds the set of returned geometries | {yes} | {yes} | {no} | {no} | {no} | {no}
|Function | Description | PostgresSQL | Oracle 10g/11g | MySQL | SQLServer | GeoDB (H2) | DB2 | CockroachDB
|Basic functions on Geometry | | | | | | | |
|`int dimension(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`String geometrytype(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`int srid(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`Geometry envelope(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`String astext(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`byte[] asbinary(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean isempty(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean issimple(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`Geometry boundary(Geometry)` | SFS §2.1.1.1 | {yes} | {yes} | {no} | {yes} | {yes} | {yes} | {yes}
|Functions for testing Spatial Relations between geometric objects | | | | | | | |
|`boolean equals(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean disjoint(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean intersects(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean touches(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean crosses(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean within(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean contains(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean overlaps(Geometry, Geometry)` | SFS §2.1.1.2 | {yes} | {yes} | {yes} | {yes} | {yes} | {yes} | {yes}
|`boolean relate(Geometry, Geometry, String)` | SFS §2.1.1.2 | {yes} | {yes} | {no} | {yes} | {yes} | {yes} | {yes}
|Functions that support Spatial Analysis | | | | | | | |
|`double distance(Geometry, Geometry)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes} | {yes}
|`Geometry buffer(Geometry, double)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes} | {yes}
|`Geometry convexhull(Geometry)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}^(1)^ | {no}
|`Geometry intersection(Geometry, Geometry)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}^(1)^ | {yes}
|`Geometry geomunion(Geometry, Geometry)` | SFS §2.1.1.3 (renamed from union) | {yes} | {yes} | {no} | {yes} | {yes} | {yes}^(1)^ | {yes}
|`Geometry difference(Geometry, Geometry)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}^(1)^ | {yes}
|`Geometry symdifference(Geometry, Geometry)` | SFS §2.1.1.3 | {yes} | {yes} | {no} | {yes} | {yes} | {yes}^(1)^ | {yes}
|Common non-SFS functions | | | | | | | |
|`boolean dwithin(Geometry, Geometry, double)` | Returns true if the geometries are within the specified distance of one another | {yes} | {yes} | {no} | {no} | {yes} | {yes} | {yes}
|`Geometry transform(Geometry, int)` | Returns a new geometry with its coordinates transformed to the SRID referenced by the integer parameter | {yes} | {yes} | {no} | {no} | {no} | {no} | {yes}
|Spatial aggregate Functions | | | | | | | |
|`Geometry extent(Geometry)` | Returns a bounding box that bounds the set of returned geometries | {yes} | {yes} | {no} | {no} | {no} | {no} | {yes}
|================================
^(1)^ Argument Geometries need to have the same dimensionality.

Expand Down Expand Up @@ -191,6 +191,14 @@ The dialect `SqlServer2008Dialect` supports the `GEOMETRY` type in SQL Server 20
The `GEOGRAPHY` type is not currently supported.
====

CockroachDB::
The dialect `CockroachDB202SpatialDialect` support the `GEOMETRY` type in CockroachDB v20.2 and later.

[NOTE]
====
The `GEOGRAPHY` type is not currently supported.
====

GeoDB (H2)::
The `GeoDBDialect` supports the GeoDB a spatial extension of the H2 in-memory database.
[NOTE]
Expand Down
9 changes: 9 additions & 0 deletions gradle/databases.gradle
Expand Up @@ -226,5 +226,14 @@ ext {
// Disable prepared statement caching due to https://www.postgresql.org/message-id/CAEcMXhmmRd4-%2BNQbnjDT26XNdUoXdmntV9zdr8%3DTu8PL9aVCYg%40mail.gmail.com
'jdbc.url' : 'jdbc:postgresql://localhost:26257/defaultdb?sslmode=disable&preparedStatementCacheQueries=0'
],
cockroachdb_spatial : [
'db.dialect' : 'org.hibernate.spatial.dialect.cockroachdb.CockroachDB202SpatialDialect',
// CockroachDB uses the same pgwire protocol as PostgreSQL, so the driver is the same.
'jdbc.driver': 'org.postgresql.Driver',
'jdbc.user' : 'root',
'jdbc.pass' : '',
// Disable prepared statement caching due to https://www.postgresql.org/message-id/CAEcMXhmmRd4-%2BNQbnjDT26XNdUoXdmntV9zdr8%3DTu8PL9aVCYg%40mail.gmail.com
'jdbc.url' : 'jdbc:postgresql://localhost:26257/defaultdb?sslmode=disable&preparedStatementCacheQueries=0'
]
]
}
2 changes: 1 addition & 1 deletion gradle/libraries.gradle
Expand Up @@ -29,7 +29,7 @@ ext {

assertjVersion = '3.14.0'

geolatteVersion = '1.6.1'
geolatteVersion = '1.8.0'

shrinkwrapVersion = '1.2.6'
shrinkwrapDescriptorsVersion = '2.0.0'
Expand Down
@@ -0,0 +1,45 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/

package org.hibernate.spatial.dialect.cockroachdb;

import java.util.Map;

import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.CockroachDB201Dialect;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.dialect.postgis.PGGeometryTypeDescriptor;

/**
* An @{code SpatialDialect} for CockroachDB 20.2 and later. CockroachDB's spatial features where introduced in
* that version.
*/
public class CockroachDB202SpatialDialect extends CockroachDB201Dialect implements CockroachSpatialDialectTrait {


public CockroachDB202SpatialDialect() {
super();
registerColumnType(
PGGeometryTypeDescriptor.INSTANCE_WKB_2.getSqlType(),
"GEOMETRY"
);
for ( Map.Entry<String, SQLFunction> entry : functionsToRegister() ) {
registerFunction( entry.getKey(), entry.getValue() );
}
}

@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes(
typeContributions,
serviceRegistry
);
delegateContributeTypes( typeContributions, serviceRegistry );
}

}
@@ -0,0 +1,46 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/

package org.hibernate.spatial.dialect.cockroachdb;

import org.hibernate.boot.model.TypeContributions;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.JTSGeometryJavaTypeDescriptor;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.dialect.postgis.PGGeometryTypeDescriptor;
import org.hibernate.spatial.dialect.postgis.PostgisFunctions;
import org.hibernate.spatial.dialect.postgis.PostgisSupport;

public class CockroachDBSpatialSupport extends PostgisSupport implements SpatialDialect {

CockroachDBSpatialSupport() {
super( new CockroachDBSpatialFunctions() );
}

@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
typeContributions.contributeType( new GeolatteGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_2 ) );
typeContributions.contributeType( new JTSGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_2 ) );

typeContributions.contributeJavaTypeDescriptor( GeolatteGeometryJavaTypeDescriptor.INSTANCE );
typeContributions.contributeJavaTypeDescriptor( JTSGeometryJavaTypeDescriptor.INSTANCE );
}

}

class CockroachDBSpatialFunctions extends PostgisFunctions {

CockroachDBSpatialFunctions() {
super();
this.functionMap.remove( "geomunion" );
}

}

@@ -0,0 +1,77 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/

package org.hibernate.spatial.dialect.cockroachdb;

import org.hibernate.boot.model.TypeContributions;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;

public interface CockroachSpatialDialectTrait extends SpatialDialect {

CockroachDBSpatialSupport DELEGATE = new CockroachDBSpatialSupport();

default SpatialFunctionsRegistry functionsToRegister() {
return DELEGATE.functionsToRegister();

}

default String getSpatialRelateSQL(String columnName, int spatialRelation) {
return DELEGATE.getSpatialRelateSQL( columnName, spatialRelation );
}

default void delegateContributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
DELEGATE.contributeTypes( typeContributions, serviceRegistry );
}

/**
* Returns the SQL fragment for the SQL WHERE-expression when parsing
* <code>org.hibernate.spatial.criterion.SpatialFilterExpression</code>s
* into prepared statements.
*
* @param columnName The name of the geometry-typed column to which the filter is
* be applied
*
* @return Rhe SQL fragment for the {@code SpatialFilterExpression}
*/
default String getSpatialFilterExpression(String columnName) {
return DELEGATE.getSpatialFilterExpression( columnName );
}

@Override
default String getSpatialAggregateSQL(String columnName, int aggregation) {
return DELEGATE.getSpatialAggregateSQL( columnName, aggregation );
}

@Override
default String getDWithinSQL(String columnName) {
return DELEGATE.getDWithinSQL( columnName );
}

@Override
default String getHavingSridSQL(String columnName) {
return DELEGATE.getHavingSridSQL( columnName );
}

@Override
default String getIsEmptySQL(String columnName, boolean isEmpty) {
return DELEGATE.getIsEmptySQL( columnName, isEmpty );
}

@Override
default boolean supportsFiltering() {
return DELEGATE.supportsFiltering();
}

@Override
default boolean supports(SpatialFunction function) {
return DELEGATE.supports( function );
}

}
@@ -0,0 +1,13 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/

/**
* {@code SpatialDialect}s for CockroachDB
*/
package org.hibernate.spatial.dialect.cockroachdb;


Expand Up @@ -39,12 +39,18 @@
public class PGGeometryTypeDescriptor implements SqlTypeDescriptor {


/**
* An instance of this class
*/
public static final PGGeometryTypeDescriptor INSTANCE = new PGGeometryTypeDescriptor();
final private Wkb.Dialect wkbDialect;

public static Geometry<?> toGeometry(Object object) {
// Type descriptor instance using EWKB v1 (postgis versions < 2.2.2)
public static final PGGeometryTypeDescriptor INSTANCE_WKB_1 = new PGGeometryTypeDescriptor( Wkb.Dialect.POSTGIS_EWKB_1);
// Type descriptor instance using EWKB v2 (postgis versions >= 2.2.2, see: https://trac.osgeo.org/postgis/ticket/3181)
public static final PGGeometryTypeDescriptor INSTANCE_WKB_2 = new PGGeometryTypeDescriptor(Wkb.Dialect.POSTGIS_EWKB_2);

private PGGeometryTypeDescriptor(Wkb.Dialect dialect) {
wkbDialect = dialect;
}

public Geometry<?> toGeometry(Object object) {
if ( object == null ) {
return null;
}
Expand All @@ -55,9 +61,8 @@ public static Geometry<?> toGeometry(Object object) {
if ( pgValue.startsWith( "00" ) || pgValue.startsWith( "01" ) ) {
//we have a WKB because this pgValue starts with the bit-order byte
buffer = ByteBuffer.from( pgValue );
final WkbDecoder decoder = Wkb.newDecoder( Wkb.Dialect.POSTGIS_EWKB_1 );
final WkbDecoder decoder = Wkb.newDecoder( wkbDialect );
return decoder.decode( buffer );

}
else {
return parseWkt( pgValue );
Expand Down
Expand Up @@ -24,9 +24,9 @@
* <p>
* Created by Karel Maesen, Geovise BVBA on 29/10/16.
*/
class PostgisFunctions extends SpatialFunctionsRegistry {
public class PostgisFunctions extends SpatialFunctionsRegistry {

PostgisFunctions() {
public PostgisFunctions() {

put(
"dimension", new StandardSQLFunction(
Expand Down
Expand Up @@ -23,7 +23,7 @@ public class PostgisNoSQLMM extends PostgisDialect {
public PostgisNoSQLMM() {

registerColumnType(
PGGeometryTypeDescriptor.INSTANCE.getSqlType(),
PGGeometryTypeDescriptor.INSTANCE_WKB_1.getSqlType(),
"GEOMETRY"
);

Expand Down
Expand Up @@ -31,7 +31,7 @@ public class PostgisPG82Dialect extends PostgreSQL82Dialect implements SpatialDi
public PostgisPG82Dialect() {
super();
registerColumnType(
PGGeometryTypeDescriptor.INSTANCE.getSqlType(),
PGGeometryTypeDescriptor.INSTANCE_WKB_1.getSqlType(),
"GEOMETRY"
);
for ( Map.Entry<String, SQLFunction> entry : support.functionsToRegister() ) {
Expand Down
Expand Up @@ -31,7 +31,7 @@ public class PostgisPG91Dialect extends PostgreSQL91Dialect implements SpatialDi
public PostgisPG91Dialect() {
super();
registerColumnType(
PGGeometryTypeDescriptor.INSTANCE.getSqlType(),
PGGeometryTypeDescriptor.INSTANCE_WKB_1.getSqlType(),
"GEOMETRY"
);
for ( Map.Entry<String, SQLFunction> entry : support.functionsToRegister() ) {
Expand Down
Expand Up @@ -31,7 +31,7 @@ public class PostgisPG92Dialect extends PostgreSQL92Dialect implements SpatialDi
public PostgisPG92Dialect() {
super();
registerColumnType(
PGGeometryTypeDescriptor.INSTANCE.getSqlType(),
PGGeometryTypeDescriptor.INSTANCE_WKB_1.getSqlType(),
"GEOMETRY"
);
for ( Map.Entry<String, SQLFunction> entry : support.functionsToRegister() ) {
Expand Down
Expand Up @@ -31,7 +31,7 @@ public class PostgisPG93Dialect extends PostgreSQL93Dialect implements SpatialDi
public PostgisPG93Dialect() {
super();
registerColumnType(
PGGeometryTypeDescriptor.INSTANCE.getSqlType(),
PGGeometryTypeDescriptor.INSTANCE_WKB_1.getSqlType(),
"GEOMETRY"
);
for ( Map.Entry<String, SQLFunction> entry : support.functionsToRegister() ) {
Expand Down

0 comments on commit aba49ce

Please sign in to comment.