HHH-11790 - Support for DB2 Spatial Extender

This commit is contained in:
Karel Maesen 2018-02-21 20:42:45 +01:00
parent 69ed07217e
commit 0c5c7178b8
37 changed files with 1817 additions and 461 deletions

View File

@ -0,0 +1,8 @@
/*
* 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>.
*/
jdbcDependency "com.ibm.db2:db2jcc:11.1"

View File

@ -0,0 +1,27 @@
#
# 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>.
#
hibernate.test.new_metadata_mappings = true
hibernate.dialect org.hibernate.spatial.dialect.db2.DB2SpatialDialect
hibernate.connection.driver_class com.ibm.db2.jcc.DB2Driver
hibernate.connection.url jdbc:db2://localhost:50000/hibern8
hibernate.connection.username db2inst1
hibernate.connection.password dbinst1-pwd
hibernate.connection.pool_size 5
hibernate.show_sql true
hibernate.format_sql true
hibernate.max_fetch_depth 5
hibernate.cache.region_prefix hibernate.test
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory
## Ensures that all geometries that are retrieved are in WGS84
hibernate.spatial.db2.srid 4326

View File

@ -8,9 +8,9 @@
hibernate.test.new_metadata_mappings = true
hibernate.dialect org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect
hibernate.connection.driver_class org.postgresql.Driver
hibernate.connection.url jdbc:postgresql://localhost:5432/hibbrtru
hibernate.connection.url jdbc:postgresql://hibpg95.cctaez8ywvn2.eu-west-1.rds.amazonaws.com:5432/hibernate
hibernate.connection.username hibbrtru
hibernate.connection.password hibbrtru
hibernate.connection.password QilTygcxHwk1
hibernate.connection.pool_size 5

View File

@ -14,13 +14,11 @@ dependencies {
compile(project(':hibernate-core'))
compile('org.postgresql:postgresql:42.1.4')
compile([group: 'org.geolatte', name: 'geolatte-geom', version: '1.2.0'])
compile([group: 'org.geolatte', name: 'geolatte-geom', version: '1.3.0'])
compile(libraries.dom4j) {
transitive = false
}
testCompile(libraries.junit)
testCompile(project(':hibernate-testing'))
testCompile([group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'])

View File

@ -19,11 +19,20 @@ public class HibernateSpatialConfigurationSettings implements Serializable {
private HibernateSpatialConfigurationSettings() {
//prevent this object from being instantiated
}
/**
* The canonical class name to use as Oracle ConnectionFinder implementation.
* The canonical class name of the Oracle ConnectionFinder implementation that will be used by the
* Oracle spatial dialects
*/
public static final String CONNECTION_FINDER = "hibernate.spatial.connection_finder";
/**
* SRID to use for the DB2 Spatial Dialects.
*
*/
public static final String DB2_DEFAULT_SRID = "hibernate.spatial.db2.srid";
}

View File

@ -18,4 +18,9 @@ public interface SpatialAggregate {
*/
public static final int EXTENT = 1;
/**
* Enum value for union aggregate (only supported in DB2)
*/
public static final int UNION = 2;
}

View File

@ -0,0 +1,115 @@
/*
* 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.db2;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.db.db2.Db2ClobDecoder;
import org.geolatte.geom.codec.db.db2.Db2ClobEncoder;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.sql.BasicBinder;
import org.hibernate.type.descriptor.sql.BasicExtractor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
/**
* Type Descriptor for the DB2 Geometry type (as Clob)
* <p>
* Created by Karel Maesen, Geovise BVBA, and David Adler, Adtech Geospatial
*/
public class DB2GeometryTypeDescriptor implements SqlTypeDescriptor {
private final Integer srid;
public DB2GeometryTypeDescriptor(Integer srid) {
this.srid = srid;
}
@Override
public int getSqlType() {
return Types.CLOB;
}
@Override
public boolean canBeRemapped() {
return false;
}
@Override
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
st.setObject( index, toText( value, options ) );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
st.setObject( name, toText( value, options ) );
}
private String toText(X value, WrapperOptions options) {
final Geometry<?> geometry = getJavaDescriptor().unwrap( value, Geometry.class, options );
final Db2ClobEncoder encoder = new Db2ClobEncoder();
String encoded = encoder.encode( geometry );
return encoded;
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
@Override
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
return getJavaDescriptor().wrap( toGeometry( rs.getObject( name ) ), options );
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
return getJavaDescriptor().wrap( toGeometry( statement.getObject( index ) ), options );
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
return getJavaDescriptor().wrap( toGeometry( statement.getObject( name ) ), options );
}
};
}
public Geometry<?> toGeometry(Object object) {
if ( object == null ) {
return null;
}
if ( object instanceof Clob ) {
Db2ClobDecoder decoder = new Db2ClobDecoder(srid);
return decoder.decode( (Clob) object );
}
throw new IllegalStateException( "Object of type " + object.getClass()
.getCanonicalName() + " not handled by DB2 as spatial value" );
}
}

View File

@ -0,0 +1,315 @@
/*
* 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.db2;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.HibernateSpatialConfigurationSettings;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.SpatialAggregate;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.SpatialRelation;
import org.hibernate.type.StandardBasicTypes;
/**
* @author David Adler, Adtech Geospatial
* creation-date: 5/22/2014
*/
public class DB2SpatialDialect extends DB2Dialect implements SpatialDialect {
/**
*
*/
private static final long serialVersionUID = 1L;
private final Map<Integer, String> spatialRelationNames = new HashMap<>();
/**
* Construct a DB2Spatial dialect. Register the geometry type and spatial
* functions supported.
*/
public DB2SpatialDialect() {
super();
registerSpatialType();
registerSpatialFunctions();
initializeRelationNames();
}
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
final DB2GeometryTypeDescriptor typeDescriptor = mkDescriptor( serviceRegistry );
typeContributions.contributeType( new GeolatteGeometryType( typeDescriptor ) );
typeContributions.contributeType( new JTSGeometryType( typeDescriptor ) );
}
private DB2GeometryTypeDescriptor mkDescriptor(ServiceRegistry serviceRegistry) {
ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
Integer srid = retrieveSridFromConfiguration( configurationService );
return new DB2GeometryTypeDescriptor( srid );
}
private Integer retrieveSridFromConfiguration(ConfigurationService configurationService) {
Integer srid = 0;
try {
srid = Integer.parseInt( configurationService.getSetting(
HibernateSpatialConfigurationSettings.DB2_DEFAULT_SRID,
String.class,
"0"
) );
}
catch (NumberFormatException e) {
throw new HibernateException(
"Invalid format for configuration parameter (Integer expected): " + HibernateSpatialConfigurationSettings.DB2_DEFAULT_SRID,
e
);
}
return srid;
}
/**
* Set up the map relating Hibernate Spatial relation constants to DB2 function names.
*/
private void initializeRelationNames() {
spatialRelationNames.put( SpatialRelation.EQUALS, "ST_EQUALS" );
spatialRelationNames.put( SpatialRelation.DISJOINT, "ST_DISJOINT" );
spatialRelationNames.put( SpatialRelation.TOUCHES, "ST_TOUCHES" );
spatialRelationNames.put( SpatialRelation.CROSSES, "ST_CROSSES" );
spatialRelationNames.put( SpatialRelation.WITHIN, "ST_WITHIN" );
spatialRelationNames.put( SpatialRelation.OVERLAPS, "ST_OVERLAPS" );
spatialRelationNames.put( SpatialRelation.CONTAINS, "ST_CONTAINS" );
spatialRelationNames.put( SpatialRelation.INTERSECTS, "ST_INTERSECTS" );
}
/**
* Register the spatial type.
* The type, CLOB or BLOB is defined in DB2GeometryTypeDescriptor and must match
* the type specified in the DB2_PROGRAM transform function.
*/
private void registerSpatialType() {
// Register Geometry column type
registerColumnType( java.sql.Types.CLOB, " db2gse.ST_Geometry" );
}
/**
* Register the spatial functions supported.
*/
private void registerSpatialFunctions() {
// Register functions used as spatial predicates
// The first parameter of registerFunction is the name that Hibernate looks for in the HQL.
// The first parameter of StandardSQLFunction is the DB2 spatial function name that will replace it.
// The second parameter of StandardSQLFunction is the return type of the function, always integer for functions used as predicates.
// This is used by Hibernate independent of Hibernate Spatial.
//
// Note that this somewhat duplicates the information in spatialRelationNames used by getSpatialRelateSQL which
// is invoked by Hibernate Spatial to handle SpatialRelateExpression when this is used in a Criteria.
registerFunction( "equals", new StandardSQLFunction(
"db2gse.ST_Equals",
StandardBasicTypes.NUMERIC_BOOLEAN
) );
registerFunction( "disjoint", new StandardSQLFunction(
"db2gse.ST_Disjoint",
StandardBasicTypes.NUMERIC_BOOLEAN
) );
registerFunction( "touches", new StandardSQLFunction(
"db2gse.ST_Touches",
StandardBasicTypes.NUMERIC_BOOLEAN
) );
registerFunction( "crosses", new StandardSQLFunction(
"db2gse.ST_Crosses",
StandardBasicTypes.NUMERIC_BOOLEAN
) );
registerFunction( "within", new StandardSQLFunction(
"db2gse.ST_Within",
StandardBasicTypes.NUMERIC_BOOLEAN
) );
registerFunction( "overlaps", new StandardSQLFunction(
"db2gse.ST_Overlaps",
StandardBasicTypes.NUMERIC_BOOLEAN
) );
registerFunction( "contains", new StandardSQLFunction(
"db2gse.ST_Contains",
StandardBasicTypes.NUMERIC_BOOLEAN
) );
registerFunction( "intersects", new StandardSQLFunction(
"db2gse.ST_Intersects",
StandardBasicTypes.NUMERIC_BOOLEAN
) );
registerFunction( "relate", new StandardSQLFunction(
"db2gse.ST_Relate",
StandardBasicTypes.NUMERIC_BOOLEAN
) );
// Register functions on Geometry
registerFunction( "dimension", new StandardSQLFunction(
"db2gse.ST_Dimension",
StandardBasicTypes.INTEGER
) );
registerFunction( "geometrytype", new StandardSQLFunction(
"db2gse.ST_GeometryType",
StandardBasicTypes.STRING
) );
registerFunction( "srid", new StandardSQLFunction(
"db2gse.ST_Srsid",
StandardBasicTypes.INTEGER
) );
registerFunction( "envelope", new StandardSQLFunction(
"db2gse.ST_Envelope"
) );
registerFunction( "astext", new StandardSQLFunction(
"db2gse.ST_AsText",
StandardBasicTypes.STRING
) );
registerFunction( "asbinary", new StandardSQLFunction(
"db2gse.ST_AsBinary",
StandardBasicTypes.BINARY
) );
registerFunction( "isempty", new StandardSQLFunction(
"db2gse.ST_IsEmpty",
StandardBasicTypes.NUMERIC_BOOLEAN
) );
registerFunction( "issimple", new StandardSQLFunction(
"db2gse.ST_IsSimple",
StandardBasicTypes.NUMERIC_BOOLEAN
) );
registerFunction( "boundary", new StandardSQLFunction(
"db2gse.ST_Boundary"
) );
// Register functions that support spatial analysis
registerFunction( "distance", new StandardSQLFunction(
"db2gse.ST_Distance",
StandardBasicTypes.DOUBLE
) );
registerFunction( "buffer", new StandardSQLFunction(
"db2gse.ST_Buffer"
) );
registerFunction( "convexhull", new StandardSQLFunction(
"db2gse.ST_ConvexHull"
) );
registerFunction( "intersection", new StandardSQLFunction(
"db2gse.ST_Intersection"
) );
registerFunction( "geomunion", new StandardSQLFunction(
"db2gse.ST_Union"
) );
registerFunction( "difference", new StandardSQLFunction(
"db2gse.ST_Difference"
) );
registerFunction( "symdifference", new StandardSQLFunction(
"db2gse.ST_SymDifference"
) );
// Register non-SFS functions listed in Hibernate Spatial
// // The srid parameter needs to be explicitly cast to INTEGER to avoid a -245 SQLCODE,
// // ambiguous parameter.
// registerFunction( "transform", new SQLFunctionTemplate(
// geolatteGemetryType,
// "DB2GSE.ST_Transform(?1, CAST (?2 AS INTEGER))"
// ) );
registerFunction( "geomFromText", new StandardSQLFunction(
"DB2GSE.ST_GeomFromText"
) );
// // Register spatial aggregate function
// registerFunction( "extent", new SQLFunctionTemplate(
// geolatteGemetryType,
// "db2gse.ST_GetAggrResult(MAX(db2gse.st_BuildMBRAggr(?1)))"
// ) );
}
@Override
public String getDWithinSQL(String columnName) {
return "db2gse.ST_Distance(" + columnName + ",?) < ?";
}
@Override
public String getHavingSridSQL(String columnName) {
return "( db2gse.ST_srsid(" + columnName + ") = ?)";
}
@Override
public String getIsEmptySQL(String columnName, boolean isEmpty) {
if ( isEmpty ) {
return "( db2gse.ST_IsEmpty(" + columnName + ") = 1)";
}
else {
return "( db2gse.ST_IsEmpty(" + columnName + ") = 0)";
}
}
@Override
public String getSpatialAggregateSQL(String columnName, int type) {
switch ( type ) {
case SpatialAggregate.EXTENT: // same as extent function above???
return "db2gse.ST_GetAggrResult(MAX(db2gse.st_BuildMBRAggr(" + columnName + ")))";
case SpatialAggregate.UNION:
return "db2gse.ST_GetAggrResult(MAX(db2gse.st_BuildUnionAggr(" + columnName + ")))";
default:
throw new IllegalArgumentException(
"Aggregation of type "
+ type + " are not supported by this dialect"
);
}
}
@Override
public String getSpatialFilterExpression(String arg0) {
throw new UnsupportedOperationException( "DB2 Dialect doesn't support spatial filtering" );
}
//Temporary Fix for HHH-6074
@Override
public String getTypeName(int code, long length, int precision, int scale) throws HibernateException {
if ( code == 3000 ) {
return "DB2GSE.ST_GEOMETRY";
}
return super.getTypeName( code, length, precision, scale );
}
@Override
public String getSpatialRelateSQL(String columnName, int spatialRelation) {
String relationName = spatialRelationNames.get( spatialRelation );
if ( relationName != null ) {
if ( spatialRelation != SpatialRelation.DISJOINT ) {
return " db2gse." + relationName + "(" + columnName + ", ?) = 1 SELECTIVITY .0001";
}
else { // SELECTIVITY not supported for ST_Disjoint UDF
return " db2gse." + relationName + "(" + columnName + ", ?) = 1";
}
}
else {
throw new IllegalArgumentException(
"Spatial relation " + spatialRelation + " not implemented" );
}
}
@Override
public boolean supports(SpatialFunction function) {
return (getFunctions().get( function.toString() ) != null);
}
@Override
public boolean supportsFiltering() {
return false;
}
}

View File

@ -0,0 +1,184 @@
package org.hibernate.spatial.integration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//import org.geolatte.geom.C3DM;
//import org.geolatte.geom.Geometry;
//import org.geolatte.geom.GeometryEquality;
//import org.geolatte.geom.GeometryPointEquality;
import org.geolatte.geom.codec.WktDecodeException;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.Dialect;
import org.hibernate.spatial.integration.geolatte.GeomEntity;
import org.hibernate.spatial.testing.GeometryEquality;
import org.hibernate.spatial.testing.SpatialFunctionalTestCase;
import org.hibernate.spatial.testing.TestDataElement;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* Created by Karel Maesen, Geovise BVBA on 15/02/2018.
*/
public abstract class AbstractTestStoreRetrieve<G, E extends GeomEntityLike<G>> extends SpatialFunctionalTestCase {
public void prepareTest() {
}
protected abstract GeometryEquality<G> getGeometryEquality();
protected abstract Class<E> getGeomEntityClass();
protected abstract E createFrom(TestDataElement element, Dialect dialect);
@Test
public void testAfterStoreRetrievingEqualObject() throws WktDecodeException {
Map<Integer, E> stored = new HashMap<>();
//check whether we retrieve exactly what we store
storeTestObjects( stored );
retrieveAndCompare( stored );
}
@Test
public void testStoringNullGeometries() {
storeNullGeometry();
retrieveNullGeometry();
}
private void retrieveAndCompare(Map<Integer, E> stored) {
int id = -1;
Transaction tx = null;
Session session = null;
GeometryEquality<G> geomEq = getGeometryEquality();
try {
session = openSession();
tx = session.beginTransaction();
for ( E storedEntity : stored.values() ) {
id = storedEntity.getId();
E retrievedEntity = (E) session.get( getGeomEntityClass(), id );
G retrievedGeometry = retrievedEntity.getGeom();
G storedGeometry = storedEntity.getGeom();
String msg = createFailureMessage( storedEntity.getId(), storedGeometry, retrievedGeometry );
assertTrue( msg, geomEq.test( storedGeometry, retrievedGeometry ) );
}
tx.commit();
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
throw new RuntimeException( String.format( "Failure on case: %d", id ), e );
}
finally {
if ( session != null ) {
session.close();
}
}
}
private String createFailureMessage(int id, G storedGeometry, G retrievedGeometry) {
String expectedText = ( storedGeometry != null ? storedGeometry.toString() : "NULL" );
String retrievedText = ( retrievedGeometry != null ? retrievedGeometry.toString() : "NULL" );
return String.format(
"Equality testsuite-suite failed for %d.%nExpected: %s%nReceived:%s",
id,
expectedText,
retrievedText
);
}
private void storeTestObjects(Map<Integer, E> stored) {
Session session = null;
Transaction tx = null;
int id = -1;
try {
session = openSession();
Dialect dialect = sessionFactory().getJdbcServices().getDialect();
// Every testsuite-suite instance is committed seperately
// to improve feedback in case of failure
for ( TestDataElement element : testData ) {
id = element.id;
tx = session.beginTransaction();
;
E entity = createFrom( element, dialect );
stored.put( entity.getId(), entity );
session.save( entity );
tx.commit();
}
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
throw new RuntimeException( "Failed storing testsuite-suite object with id:" + id, e );
}
finally {
if ( session != null ) {
session.close();
}
}
}
private void storeNullGeometry() {
GeomEntity entity = null;
Session session = null;
Transaction tx = null;
try {
session = openSession();
tx = session.beginTransaction();
entity = new GeomEntity();
entity.setId( 1 );
entity.setType( "NULL OBJECT" );
session.save( entity );
tx.commit();
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
Integer id = entity != null ? entity.getId() : -1;
throw new RuntimeException( "Failed storing testsuite-suite object with id:" + id, e );
}
finally {
if ( session != null ) {
session.close();
}
}
}
private void retrieveNullGeometry() {
Transaction tx = null;
Session session = null;
try {
session = openSession();
tx = session.beginTransaction();
Criteria criteria = session.createCriteria( GeomEntity.class );
List<GeomEntity> retrieved = criteria.list();
assertEquals( "Expected exactly one result", 1, retrieved.size() );
GeomEntity entity = retrieved.get( 0 );
assertNull( entity.getGeom() );
tx.commit();
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
throw new RuntimeException( e );
}
finally {
if ( session != null ) {
session.close();
}
}
}
}

View File

@ -0,0 +1,28 @@
package org.hibernate.spatial.integration;
import org.geolatte.geom.codec.Wkt;
import org.geolatte.geom.codec.WktDecoder;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.spatial.dialect.db2.DB2SpatialDialect;
/**
* Created by Karel Maesen, Geovise BVBA on 15/02/2018.
*/
public class DecodeUtil {
public static WktDecoder getWktDecoder(Dialect dialect) {
WktDecoder decoder = null;
if ( dialect instanceof AbstractHANADialect ) {
decoder = Wkt.newDecoder( Wkt.Dialect.HANA_EWKT );
}
else if ( dialect instanceof DB2SpatialDialect ) {
decoder = Wkt.newDecoder( Wkt.Dialect.DB2_WKT );
}
else{
decoder = Wkt.newDecoder( Wkt.Dialect.POSTGIS_EWKT_1 );
}
return decoder;
}
}

View File

@ -0,0 +1,27 @@
package org.hibernate.spatial.integration;
import org.geolatte.geom.codec.WktDecodeException;
import org.geolatte.geom.codec.WktDecoder;
import org.hibernate.dialect.Dialect;
import org.hibernate.spatial.testing.TestDataElement;
import static org.hibernate.spatial.integration.DecodeUtil.getWktDecoder;
/**
* Created by Karel Maesen, Geovise BVBA on 15/02/2018.
*/
public interface GeomEntityLike<G> {
Integer getId();
void setId(Integer id);
String getType();
void setType(String type);
G getGeom();
void setGeom(G geom);
}

View File

@ -11,15 +11,16 @@ import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.spatial.integration.GeomEntityLike;
import org.hibernate.spatial.testing.TestDataElement;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkt;
import org.geolatte.geom.codec.WktDecodeException;
import org.geolatte.geom.codec.WktDecoder;
import static org.hibernate.spatial.integration.DecodeUtil.getWktDecoder;
/**
* Test class used in unit testing.
*
@ -29,7 +30,18 @@ import org.geolatte.geom.codec.WktDecoder;
*/
@Entity
@Table(name = "geomtest")
public class GeomEntity {
public class GeomEntity implements GeomEntityLike<Geometry> {
static GeomEntity createFrom(TestDataElement element, Dialect dialect) throws WktDecodeException {
WktDecoder decoder = getWktDecoder( dialect );
Geometry geom = decoder.decode( element.wkt );
GeomEntity result = new GeomEntity();
result.setId( element.id );
result.setGeom( geom );
result.setType( element.type );
return result;
}
@Id
private Integer id;
@ -38,45 +50,36 @@ public class GeomEntity {
private Geometry geom;
@Override
public Integer getId() {
return id;
}
@Override
public void setId(Integer id) {
this.id = id;
}
@Override
public String getType() {
return type;
}
@Override
public void setType(String type) {
this.type = type;
}
@Override
public Geometry getGeom() {
return geom;
}
@Override
public void setGeom(Geometry geom) {
this.geom = geom;
}
public static GeomEntity createFrom(TestDataElement element, Dialect dialect) throws WktDecodeException {
WktDecoder decoder = null;
if (dialect instanceof AbstractHANADialect) {
decoder = Wkt.newDecoder( Wkt.Dialect.HANA_EWKT );
}
else {
decoder = Wkt.newDecoder( Wkt.Dialect.POSTGIS_EWKT_1 );
}
Geometry geom = decoder.decode( element.wkt );
GeomEntity result = new GeomEntity();
result.setId( element.id );
result.setGeom( geom );
result.setType( element.type );
return result;
}
@Override
public boolean equals(Object o) {

View File

@ -6,28 +6,20 @@
*/
package org.hibernate.spatial.integration.geolatte;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.geolatte.geom.C3DM;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.GeometryEquality;
import org.geolatte.geom.GeometryPointEquality;
import org.geolatte.geom.codec.WktDecodeException;
import org.jboss.logging.Logger;
import org.junit.Test;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.Dialect;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.integration.AbstractTestStoreRetrieve;
import org.hibernate.spatial.integration.GeomEntityLike;
import org.hibernate.spatial.testing.GeolatteGeometryEquality;
import org.hibernate.spatial.testing.GeometryEquality;
import org.hibernate.spatial.testing.SpatialDialectMatcher;
import org.hibernate.spatial.testing.SpatialFunctionalTestCase;
import org.hibernate.spatial.testing.TestDataElement;
import org.hibernate.testing.Skip;
import static junit.framework.Assert.assertEquals;
@ -39,7 +31,7 @@ import static org.junit.Assert.assertTrue;
* are equal to the <code>Geometry</code>s stored.
*/
@Skip(condition = SpatialDialectMatcher.class, message = "No Spatial Dialect")
public class TestStoreRetrieveUsingGeolatte extends SpatialFunctionalTestCase {
public class TestStoreRetrieveUsingGeolatte extends AbstractTestStoreRetrieve<Geometry, GeomEntity> {
private static HSMessageLogger LOG = Logger.getMessageLogger(
HSMessageLogger.class,
@ -50,148 +42,19 @@ public class TestStoreRetrieveUsingGeolatte extends SpatialFunctionalTestCase {
return LOG;
}
public void prepareTest() {
@Override
protected GeometryEquality getGeometryEquality() {
return new GeolatteGeometryEquality();
}
@Test
public void testAfterStoreRetrievingEqualObject() throws WktDecodeException {
Map<Integer, GeomEntity> stored = new HashMap<Integer, GeomEntity>();
//check whether we retrieve exactly what we store
storeTestObjects( stored );
retrieveAndCompare( stored );
@Override
protected Class getGeomEntityClass() {
return GeomEntity.class;
}
@Test
public void testStoringNullGeometries() {
storeNullGeometry();
retrieveNullGeometry();
}
private void retrieveAndCompare(Map<Integer, GeomEntity> stored) {
int id = -1;
Transaction tx = null;
Session session = null;
GeometryEquality geomEq = new GeometryPointEquality();
try {
session = openSession();
tx = session.beginTransaction();
for ( GeomEntity storedEntity : stored.values() ) {
id = storedEntity.getId();
GeomEntity retrievedEntity = (GeomEntity) session.get( GeomEntity.class, id );
Geometry<C3DM> retrievedGeometry = retrievedEntity.getGeom();
Geometry<C3DM> storedGeometry = storedEntity.getGeom();
String msg = createFailureMessage( storedEntity.getId(), storedGeometry, retrievedGeometry );
assertTrue( msg, geomEq.equals( storedGeometry, retrievedGeometry ) );
}
tx.commit();
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
throw new RuntimeException( String.format( "Failure on case: %d", id ), e );
}
finally {
if ( session != null ) {
session.close();
}
}
}
private String createFailureMessage(int id, Geometry storedGeometry, Geometry retrievedGeometry) {
String expectedText = ( storedGeometry != null ? storedGeometry.toString() : "NULL" );
String retrievedText = ( retrievedGeometry != null ? retrievedGeometry.toString() : "NULL" );
return String.format(
"Equality testsuite-suite failed for %d.%nExpected: %s%nReceived:%s",
id,
expectedText,
retrievedText
);
}
private void storeTestObjects(Map<Integer, GeomEntity> stored) {
Session session = null;
Transaction tx = null;
int id = -1;
try {
session = openSession();
Dialect dialect = sessionFactory().getSessionFactory().getJdbcServices().getDialect();
// Every testsuite-suite instance is committed seperately
// to improve feedback in case of failure
for ( TestDataElement element : testData ) {
id = element.id;
tx = session.beginTransaction();
;
GeomEntity entity = GeomEntity.createFrom( element, dialect );
stored.put( entity.getId(), entity );
session.save( entity );
tx.commit();
}
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
throw new RuntimeException( "Failed storing testsuite-suite object with id:" + id, e );
}
finally {
if ( session != null ) {
session.close();
}
}
}
private void storeNullGeometry() {
GeomEntity entity = null;
Session session = null;
Transaction tx = null;
try {
session = openSession();
tx = session.beginTransaction();
entity = new GeomEntity();
entity.setId( 1 );
entity.setType( "NULL OBJECT" );
session.save( entity );
tx.commit();
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
Integer id = entity != null ? entity.getId() : -1;
throw new RuntimeException( "Failed storing testsuite-suite object with id:" + id, e );
}
finally {
if ( session != null ) {
session.close();
}
}
}
private void retrieveNullGeometry() {
Transaction tx = null;
Session session = null;
try {
session = openSession();
tx = session.beginTransaction();
Criteria criteria = session.createCriteria( GeomEntity.class );
List<GeomEntity> retrieved = criteria.list();
assertEquals( "Expected exactly one result", 1, retrieved.size() );
GeomEntity entity = retrieved.get( 0 );
assertNull( entity.getGeom() );
tx.commit();
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
throw new RuntimeException( e );
}
finally {
if ( session != null ) {
session.close();
}
}
@Override
protected GeomEntity createFrom(
TestDataElement element, Dialect dialect) throws WktDecodeException {
return GeomEntity.createFrom( element, dialect );
}
}

View File

@ -18,14 +18,17 @@ import org.geolatte.geom.codec.WktDecoder;
import org.geolatte.geom.jts.JTS;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.spatial.integration.GeomEntityLike;
import org.hibernate.spatial.testing.TestDataElement;
import static org.hibernate.spatial.integration.DecodeUtil.getWktDecoder;
/**
* Test class used in unit testing.
*/
@Entity
@Table(name = "geomtest")
public class GeomEntity {
public class GeomEntity implements GeomEntityLike<Geometry> {
@Id
@ -60,13 +63,7 @@ public class GeomEntity {
}
public static GeomEntity createFrom(TestDataElement element, Dialect dialect) throws ParseException {
WktDecoder decoder = null;
if (dialect instanceof AbstractHANADialect) {
decoder = Wkt.newDecoder( Wkt.Dialect.HANA_EWKT );
}
else {
decoder = Wkt.newDecoder( Wkt.Dialect.POSTGIS_EWKT_1 );
}
WktDecoder decoder = getWktDecoder( dialect );
Geometry geom = JTS.to( decoder.decode( element.wkt ) );
GeomEntity result = new GeomEntity();
result.setId( element.id );

View File

@ -6,37 +6,27 @@
*/
package org.hibernate.spatial.integration.jts;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import org.jboss.logging.Logger;
import org.junit.Test;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.Dialect;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.integration.AbstractTestStoreRetrieve;
import org.hibernate.spatial.testing.GeometryEquality;
import org.hibernate.spatial.testing.JTSGeometryEquality;
import org.hibernate.spatial.testing.SpatialDialectMatcher;
import org.hibernate.spatial.testing.SpatialFunctionalTestCase;
import org.hibernate.spatial.testing.TestDataElement;
import org.hibernate.testing.Skip;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.hibernate.testing.Skip;
/**
* This testsuite-suite class verifies whether the <code>Geometry</code>s retrieved
* are equal to the <code>Geometry</code>s stored.
*/
@Skip(condition = SpatialDialectMatcher.class, message = "No Spatial Dialect")
public class TestStoreRetrieveUsingJTS extends SpatialFunctionalTestCase {
public class TestStoreRetrieveUsingJTS extends AbstractTestStoreRetrieve<Geometry, GeomEntity> {
private static final HSMessageLogger LOG = Logger.getMessageLogger(
HSMessageLogger.class,
@ -48,146 +38,26 @@ public class TestStoreRetrieveUsingJTS extends SpatialFunctionalTestCase {
return LOG;
}
public void prepareTest() {
@Override
protected GeometryEquality<Geometry> getGeometryEquality() {
return new JTSGeometryEquality();
}
@Test
public void testAfterStoreRetrievingEqualObject() throws ParseException {
Map<Integer, GeomEntity> stored = new HashMap<Integer, GeomEntity>();
//check whether we retrieve exactly what we store
storeTestObjects( stored );
retrieveAndCompare( stored );
@Override
protected Class<GeomEntity> getGeomEntityClass() {
return GeomEntity.class;
}
@Test
public void testStoringNullGeometries() {
storeNullGeometry();
retrieveNullGeometry();
}
private void retrieveAndCompare(Map<Integer, GeomEntity> stored) {
int id = -1;
Transaction tx = null;
Session session = null;
@Override
protected GeomEntity createFrom(
TestDataElement element, Dialect dialect) {
try {
session = openSession();
tx = session.beginTransaction();
for ( GeomEntity storedEntity : stored.values() ) {
id = storedEntity.getId();
GeomEntity retrievedEntity = (GeomEntity) session.get( GeomEntity.class, id );
Geometry retrievedGeometry = retrievedEntity.getGeom();
Geometry storedGeometry = storedEntity.getGeom();
String msg = createFailureMessage( storedEntity.getId(), storedGeometry, retrievedGeometry );
assertTrue( msg, geometryEquality.test( storedGeometry, retrievedGeometry ) );
}
tx.commit();
return GeomEntity.createFrom( element, dialect );
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
throw new RuntimeException( String.format( "Failure on case: %d", id ), e );
}
finally {
if ( session != null ) {
session.close();
}
}
}
private String createFailureMessage(int id, Geometry storedGeometry, Geometry retrievedGeometry) {
String expectedText = ( storedGeometry != null ? storedGeometry.toText() : "NULL" );
String retrievedText = ( retrievedGeometry != null ? retrievedGeometry.toText() : "NULL" );
return String.format(
"Equality testsuite-suite failed for %d.%nExpected: %s%nReceived:%s",
id,
expectedText,
retrievedText
);
}
private void storeTestObjects(Map<Integer, GeomEntity> stored) {
Session session = null;
Transaction tx = null;
int id = -1;
try {
session = openSession();
Dialect dialect = sessionFactory().getSessionFactory().getJdbcServices().getDialect();
// Every testsuite-suite instance is committed seperately
// to improve feedback in case of failure
for ( TestDataElement element : testData ) {
id = element.id;
tx = session.beginTransaction();
GeomEntity entity = GeomEntity.createFrom( element, dialect );
stored.put( entity.getId(), entity );
session.save( entity );
tx.commit();
}
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
throw new RuntimeException( "Failed storing testsuite-suite object with id:" + id, e );
}
finally {
if ( session != null ) {
session.close();
}
}
}
private void storeNullGeometry() {
GeomEntity entity = null;
Session session = null;
Transaction tx = null;
try {
session = openSession();
tx = session.beginTransaction();
entity = new GeomEntity();
entity.setId( 1 );
entity.setType( "NULL OBJECT" );
session.save( entity );
tx.commit();
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
Integer id = entity != null ? entity.getId() : -1;
throw new RuntimeException( "Failed storing testsuite-suite object with id:" + id, e );
}
finally {
if ( session != null ) {
session.close();
}
}
}
private void retrieveNullGeometry() {
Transaction tx = null;
Session session = null;
try {
session = openSession();
tx = session.beginTransaction();
Criteria criteria = session.createCriteria( GeomEntity.class );
List<GeomEntity> retrieved = criteria.list();
assertEquals( "Expected exactly one result", 1, retrieved.size() );
GeomEntity entity = retrieved.get( 0 );
assertNull( entity.getGeom() );
tx.commit();
}
catch ( Exception e ) {
if ( tx != null ) {
tx.rollback();
}
catch (ParseException e) {
throw new RuntimeException( e );
}
finally {
if ( session != null ) {
session.close();
}
}
}
}

View File

@ -785,7 +785,8 @@ public abstract class AbstractExpectationsFactory {
try {
cn = createConnection();
preparedStatement = nativeSQLStatement.prepare( cn );
LOG.info( "Native SQL is: " + preparedStatement.toString() );
LOG.info( "Native SQL is: " + nativeSQLStatement.toString() );
results = preparedStatement.executeQuery();
while ( results.next() ) {
int id = results.getInt( 1 );
@ -851,6 +852,9 @@ public abstract class AbstractExpectationsFactory {
public PreparedStatement prepare(Connection connection) throws SQLException {
return connection.prepareStatement( sql );
}
public String toString() {
return sql;
}
};
}
@ -863,6 +867,9 @@ public abstract class AbstractExpectationsFactory {
}
return pstmt;
}
public String toString(){
return String.format("sql; %s, wkt: %s", sql, wkt);
}
};
}
@ -876,6 +883,9 @@ public abstract class AbstractExpectationsFactory {
}
return pstmt;
}
public String toString(){
return sql;
}
};
}

View File

@ -0,0 +1,28 @@
package org.hibernate.spatial.testing;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.GeometryPointEquality;
import org.geolatte.geom.Position;
/**
* Created by Karel Maesen, Geovise BVBA on 15/02/2018.
*/
public class GeolatteGeometryEquality<P extends Position> implements GeometryEquality<Geometry<P>>{
private final org.geolatte.geom.GeometryEquality delegate;
public GeolatteGeometryEquality(){
this( new GeometryPointEquality());
}
public GeolatteGeometryEquality(org.geolatte.geom.GeometryEquality delegate) {
this.delegate = delegate;
}
@Override
public boolean test(Geometry<P> geom1, Geometry<P> geom2) {
return delegate.equals( geom1, geom2 );
}
}

View File

@ -1,124 +1,10 @@
/*
* 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.testing;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
/**
* This class tests for the equality between geometries.
* <p/>
* The notion of geometric equality can differ slightly between
* spatial databases.
*
* @deprecated Should be replaced by Geolatte-geom GeometryEquality
* Created by Karel Maesen, Geovise BVBA on 15/02/2018.
*/
@Deprecated
public class GeometryEquality {
public boolean test(Geometry geom1, Geometry geom2) {
return test( geom1, geom2, false );
}
private boolean test(Geometry geom1, Geometry geom2, boolean ignoreSRID) {
if ( geom1 == null ) {
return geom2 == null;
}
if ( geom1.isEmpty() ) {
return geom2.isEmpty();
}
if ( !ignoreSRID && !equalSRID( geom1, geom2 ) ) {
return false;
}
if ( geom1 instanceof GeometryCollection ) {
if ( !(geom2 instanceof GeometryCollection) ) {
return false;
}
GeometryCollection expectedCollection = (GeometryCollection) geom1;
GeometryCollection receivedCollection = (GeometryCollection) geom2;
for ( int partIndex = 0; partIndex < expectedCollection.getNumGeometries(); partIndex++ ) {
Geometry partExpected = expectedCollection.getGeometryN( partIndex );
Geometry partReceived = receivedCollection.getGeometryN( partIndex );
if ( !test( partExpected, partReceived, true ) ) {
return false;
}
}
return true;
}
else {
return testSimpleGeometryEquality( geom1, geom2 );
}
}
/**
* Two geometries are equal iff both have the same SRID, or both are unknown (i.e. a SRID of 0 or -1).
*
* @param geom1
* @param geom2
*
* @return
*/
private boolean equalSRID(Geometry geom1, Geometry geom2) {
return geom1.getSRID() == geom2.getSRID() ||
(geom1.getSRID() < 1 && geom2.getSRID() < 1);
}
/**
* Test whether two geometries, not of type GeometryCollection are equal.
*
* @param geom1
* @param geom2
*
* @return
*/
protected boolean testSimpleGeometryEquality(Geometry geom1, Geometry geom2) {
//return geom1.equals(geom2);
return testTypeAndVertexEquality( geom1, geom2 );
}
protected boolean testTypeAndVertexEquality(Geometry geom1, Geometry geom2) {
if ( !geom1.getGeometryType().equals( geom2.getGeometryType() ) ) {
return false;
}
if ( geom1.getNumGeometries() != geom2.getNumGeometries() ) {
return false;
}
if ( geom1.getNumPoints() != geom2.getNumPoints() ) {
return false;
}
Coordinate[] coordinates1 = geom1.getCoordinates();
Coordinate[] coordinates2 = geom2.getCoordinates();
for ( int i = 0; i < coordinates1.length; i++ ) {
Coordinate c1 = coordinates1[i];
Coordinate c2 = coordinates2[i];
if ( !testCoordinateEquality( c1, c2 ) ) {
return false;
}
}
return true;
}
private boolean testCoordinateEquality(Coordinate c1, Coordinate c2) {
// if ( c1 instanceof MCoordinate ) {
// if ( !( c2 instanceof MCoordinate ) ) {
// return false;
// }
// MCoordinate mc1 = (MCoordinate) c1;
// MCoordinate mc2 = (MCoordinate) c2;
// if ( !Double.isNaN( mc1.m ) && mc1.m != mc2.m ) {
// return false;
// }
// }
if ( !Double.isNaN( c1.z ) && c1.z != c2.z ) {
return false;
}
return c1.x == c2.x && c1.y == c2.y;
}
public interface GeometryEquality<G> {
boolean test(G geom1, G geom2);
}

View File

@ -0,0 +1,106 @@
/*
* 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.testing;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
/**
* This class tests for the equality between geometries.
* <p/>
* The notion of geometric equality can differ slightly between
* spatial databases.
*/
public class JTSGeometryEquality implements GeometryEquality<Geometry> {
@Override
public boolean test(Geometry geom1, Geometry geom2) {
if ( geom1 == null ) {
return geom2 == null;
}
if ( geom1.isEmpty() ) {
return geom2.isEmpty();
}
if ( !equalSRID( geom1, geom2 ) ) {
return false;
}
if ( geom1 instanceof GeometryCollection ) {
if ( !(geom2 instanceof GeometryCollection) ) {
return false;
}
GeometryCollection expectedCollection = (GeometryCollection) geom1;
GeometryCollection receivedCollection = (GeometryCollection) geom2;
for ( int partIndex = 0; partIndex < expectedCollection.getNumGeometries(); partIndex++ ) {
Geometry partExpected = expectedCollection.getGeometryN( partIndex );
Geometry partReceived = receivedCollection.getGeometryN( partIndex );
if ( !test( partExpected, partReceived ) ) {
return false;
}
}
return true;
}
else {
return testSimpleGeometryEquality( geom1, geom2 );
}
}
/**
* Two geometries are equal iff both have the same SRID, or both are unknown (i.e. a SRID of 0 or -1).
*
* @param geom1
* @param geom2
*
* @return
*/
private boolean equalSRID(Geometry geom1, Geometry geom2) {
return geom1.getSRID() == geom2.getSRID() ||
(geom1.getSRID() < 1 && geom2.getSRID() < 1);
}
/**
* Test whether two geometries, not of type GeometryCollection are equal.
*
* @param geom1
* @param geom2
*
* @return
*/
protected boolean testSimpleGeometryEquality(Geometry geom1, Geometry geom2) {
//return geom1.equals(geom2);
return testTypeAndVertexEquality( geom1, geom2 );
}
protected boolean testTypeAndVertexEquality(Geometry geom1, Geometry geom2) {
if ( !geom1.getGeometryType().equals( geom2.getGeometryType() ) ) {
return false;
}
if ( geom1.getNumGeometries() != geom2.getNumGeometries() ) {
return false;
}
if ( geom1.getNumPoints() != geom2.getNumPoints() ) {
return false;
}
Coordinate[] coordinates1 = geom1.getCoordinates();
Coordinate[] coordinates2 = geom2.getCoordinates();
for ( int i = 0; i < coordinates1.length; i++ ) {
Coordinate c1 = coordinates1[i];
Coordinate c2 = coordinates2[i];
if ( !testCoordinateEquality( c1, c2 ) ) {
return false;
}
}
return true;
}
private boolean testCoordinateEquality(Coordinate c1, Coordinate c2) {
return (Double.isNaN( c1.z ) || !(c1.z != c2.z)) && c1.x == c2.x && c1.y == c2.y;
}
}

View File

@ -30,4 +30,6 @@ public interface NativeSQLStatement {
* @throws SQLException
*/
public PreparedStatement prepare(Connection connection) throws SQLException;
public String toString();
}

View File

@ -42,7 +42,7 @@ public abstract class SpatialFunctionalTestCase extends BaseCoreFunctionalTestCa
protected TestData testData;
protected DataSourceUtils dataSourceUtils;
protected GeometryEquality geometryEquality;
protected JTSGeometryEquality geometryEquality;
protected AbstractExpectationsFactory expectationsFactory;
/**

View File

@ -27,8 +27,8 @@ public abstract class TestSupport {
return new DataSourceUtils( driver(), url(), user(), passwd(), getSQLExpressionTemplate() );
}
public GeometryEquality createGeometryEquality() {
return new GeometryEquality();
public JTSGeometryEquality createGeometryEquality() {
return new JTSGeometryEquality();
}
public abstract TestData createTestData(BaseCoreFunctionalTestCase testcase);

View File

@ -10,6 +10,7 @@ package org.hibernate.spatial.testing;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.PostgreSQL82Dialect;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.testing.dialects.db2.DB2TestSupport;
import org.hibernate.spatial.testing.dialects.h2geodb.GeoDBTestSupport;
import org.hibernate.spatial.testing.dialects.hana.HANATestSupport;
import org.hibernate.spatial.testing.dialects.mysql.MySQL56TestSupport;
@ -80,6 +81,10 @@ public class TestSupportFactories {
if ( "org.hibernate.spatial.dialect.hana.HANASpatialDialect".equals( canonicalName ) ) {
return HANATestSupport.class;
}
if ("org.hibernate.spatial.dialect.db2.DB2SpatialDialect".equals( canonicalName )) {
return DB2TestSupport.class;
}
throw new IllegalArgumentException( "Dialect not known in test suite" );
}

View File

@ -0,0 +1,44 @@
/*
* This file is part of Hibernate Spatial, an extension to the
* hibernate ORM solution for spatial (geographic) data.
*
* Copyright © 2014 Adtech Geospatial
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.hibernate.spatial.testing.dialects.db2;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import java.sql.SQLException;
/**
* @author David Adler, Adtech Geospatial
* creation-date: 5/22/2014
*/
public class DB2DataSourceUtils extends DataSourceUtils {
public DB2DataSourceUtils(String jdbcDriver, String jdbcUrl, String jdbcUser, String jdbcPass, SQLExpressionTemplate sqlExpressionTemplate) {
super(jdbcDriver, jdbcUrl, jdbcUser, jdbcPass, sqlExpressionTemplate);
}
private void createIndex() throws SQLException {
String sql = "create index idx_spatial_geomtest on geomtest (geom) extend using db2gse.spatial_index(0.1,0,0)";
executeStatement(sql);
}
}

View File

@ -0,0 +1,278 @@
/*
* This file is part of Hibernate Spatial, an extension to the
* hibernate ORM solution for spatial (geographic) data.
*
* Copyright © 2014 Adtech Geospatial
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.hibernate.spatial.testing.dialects.db2;
import java.sql.SQLException;
import java.util.Map;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import org.geolatte.geom.jts.JTS;
import org.hibernate.spatial.dialect.db2.DB2GeometryTypeDescriptor;
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.NativeSQLStatement;
/**
* This class provides the DB2 native spatial queries to generate the
* results which will be compared with the HQL spatial results.
*
* @author David Adler, Adtech Geospatial
* creation-date: 5/22/2014
*/
public class DB2ExpectationsFactory extends AbstractExpectationsFactory {
public DB2ExpectationsFactory(DataSourceUtils utils) {
super( utils );
}
private final DB2GeometryTypeDescriptor desc = new DB2GeometryTypeDescriptor(4326);
/**
* Returns the expected extent of all testsuite-suite geometries.
*
* @return map of identifier, extent
*
* @throws SQLException
*/
public Map<Integer, Geometry> getExtent() throws SQLException {
return retrieveExpected( createNativeExtentStatement(), GEOMETRY );
}
protected NativeSQLStatement createNativeExtentStatement() {
return createNativeSQLStatement(
"select max(t.id), db2gse.ST_GetAggrResult(MAX(db2gse.st_BuildMBRAggr(t.geom))) from GeomTest t where db2gse.st_srid(t.geom) = 4326" );
}
@Override
protected NativeSQLStatement createNativeTouchesStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_touches(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_touches(t.geom, DB2GSE.ST_geomFromText(?, 4326)) = 1 and db2gse.st_srid(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeOverlapsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_overlaps(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_overlaps(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) = 1 and db2gse.st_srid(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeRelateStatement(Geometry geom, String matrix) {
String sql = "select t.id, DB2GSE.ST_relate(t.geom, DB2GSE.ST_GeomFromText(?, 4326), '" + matrix + "' ) from GeomTest t where DB2GSE.ST_relate(t.geom, DB2GSE.ST_GeomFromText(?, 4326), '" + matrix + "') = 1 and db2gse.st_srid(t.geom) = 4326";
return createNativeSQLStatementAllWKTParams( sql, geom.toText() );
}
@Override
protected NativeSQLStatement createNativeDwithinStatement(Point geom, double distance) {
String sql = "select t.id, DB2GSE.ST_dwithin(t.geom, DB2GSE.ST_GeomFromText(?, 4326), " + distance + " ) from GeomTest t where DB2GSE.ST_dwithin(t.geom, DB2GSE.ST_GeomFromText(?, 4326), " + distance + ") = 1 and db2gse.st_srid(t.geom) = 4326";
return createNativeSQLStatementAllWKTParams( sql, geom.toText() );
}
@Override
protected NativeSQLStatement createNativeIntersectsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_intersects(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_intersects(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) = 1 and db2gse.st_srid(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeFilterStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom && ST_GeomFromText(?, 4326) from GeomTest t where DB2GSE.ST_intersects(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) = 1 and db2gse.st_srid(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeDistanceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_distance(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_SRID(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeDimensionSQL() {
return createNativeSQLStatement( "select id, DB2GSE.ST_dimension(geom) from geomtest" );
}
@Override
protected NativeSQLStatement createNativeBufferStatement(Double distance) {
return createNativeSQLStatement(
"select t.id, DB2GSE.ST_buffer(t.geom,?) from GeomTest t where DB2GSE.ST_SRID(t.geom) = 4326",
new Object[] {distance}
);
}
@Override
protected NativeSQLStatement createNativeConvexHullStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_convexhull(DB2GSE.ST_Union(t.geom, DB2GSE.ST_GeomFromText(?, 4326))) from GeomTest t where DB2GSE.ST_SRID(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeIntersectionStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_intersection(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_SRID(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeDifferenceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_difference(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_SRID(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeSymDifferenceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_symdifference(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_SRID(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeGeomUnionStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_union(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_SRID(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeTransformStatement(int epsg) {
return createNativeSQLStatement(
"select t.id, DB2GSE.ST_transform(t.geom," + epsg + ") from GeomTest t where DB2GSE.ST_SRID(t.geom) = 4326"
);
}
@Override
protected NativeSQLStatement createNativeHavingSRIDStatement(int srid) {
return createNativeSQLStatement(
"select t.id, DB2GSE.st_srid(t.geom) from GeomTest t where DB2GSE.ST_SRID(t.geom) = " + srid );
}
@Override
protected NativeSQLStatement createNativeAsTextStatement() {
return createNativeSQLStatement( "select id, DB2GSE.st_astext(geom) from geomtest" );
}
@Override
protected NativeSQLStatement createNativeSridStatement() {
return createNativeSQLStatement( "select id, DB2GSE.ST_SRID(geom) from geomtest" );
}
@Override
protected NativeSQLStatement createNativeIsSimpleStatement() {
return createNativeSQLStatement( "select id, DB2GSE.ST_issimple(geom) from geomtest" );
}
@Override
protected NativeSQLStatement createNativeIsEmptyStatement() {
return createNativeSQLStatement(
"select id, DB2GSE.ST_isempty(geom) from geomtest where db2gse.ST_IsEmpty(geom) = 1" );
}
@Override
protected NativeSQLStatement createNativeIsNotEmptyStatement() { // return 'not ST_IsEmpty', 'not' is not supported by DB2
return createNativeSQLStatement(
"select id, case when DB2GSE.ST_isempty(geom) = 0 then 1 else 0 end from geomtest where db2gse.ST_IsEmpty(geom) = 0" );
}
@Override
protected NativeSQLStatement createNativeBoundaryStatement() {
return createNativeSQLStatement( "select id, DB2GSE.ST_boundary(geom) from geomtest" );
}
@Override
protected NativeSQLStatement createNativeEnvelopeStatement() {
return createNativeSQLStatement( "select id, DB2GSE.ST_envelope(geom) from geomtest" );
}
@Override
protected NativeSQLStatement createNativeAsBinaryStatement() {
return createNativeSQLStatement( "select id, DB2GSE.ST_asbinary(geom) from geomtest" );
}
@Override
protected NativeSQLStatement createNativeGeometryTypeStatement() {
return createNativeSQLStatement( "select id, DB2GSE.ST_GeometryType(geom) from geomtest" );
}
@Override
protected NativeSQLStatement createNativeWithinStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_within(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_within(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) = 1 and db2gse.st_srid(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeEqualsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_equals(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_equals(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) = 1 and db2gse.st_srid(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeCrossesStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_crosses(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_crosses(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) = 1 and db2gse.st_srid(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeContainsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_contains(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_contains(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) = 1 and db2gse.st_srid(t.geom) = 4326",
geom.toText()
);
}
@Override
protected NativeSQLStatement createNativeDisjointStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, DB2GSE.ST_disjoint(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) from GeomTest t where DB2GSE.ST_disjoint(t.geom, DB2GSE.ST_GeomFromText(?, 4326)) = 1 and db2gse.st_srid(t.geom) = 4326",
geom.toText()
);
}
@Override
protected Geometry decode(Object o) {
org.geolatte.geom.Geometry<?> geometry = desc.toGeometry( o );
return geometry == null ? null : JTS.to( geometry );
}
}

View File

@ -0,0 +1,49 @@
/*
* This file is part of Hibernate Spatial, an extension to the
* hibernate ORM solution for spatial (geographic) data.
*
* Copyright © 2014 Adtech Geospatial
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.hibernate.spatial.testing.dialects.db2;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import org.hibernate.spatial.testing.TestDataElement;
import org.hibernate.spatial.testing.WktUtility;
/**
* @author David Adler
* creation-date: 5/22/2014
*/
public class DB2ExpressionTemplate implements SQLExpressionTemplate {
final String SQL_TEMPLATE = "insert into geomtest (id, type, geom) values (%d, '%s', DB2GSE.ST_GEOMETRY('%s', %d))";
public String toInsertSql(TestDataElement testDataElement) {
String wkt = WktUtility.getWkt( testDataElement.wkt );
int srid = WktUtility.getSRID( testDataElement.wkt );
return String.format(
SQL_TEMPLATE,
testDataElement.id,
testDataElement.type,
wkt,
srid
);
}
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of Hibernate Spatial, an extension to the
* hibernate ORM solution for spatial (geographic) data.
*
* Copyright © 2014 Adtech Geospatial
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.hibernate.spatial.testing.dialects.db2;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import org.hibernate.spatial.testing.TestData;
import org.hibernate.spatial.testing.TestSupport;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
/**
* @author David Adler, Adtech Geospatial
* creation-date: 5/22/2014
*/
public class DB2TestSupport extends TestSupport {
public TestData createTestData(BaseCoreFunctionalTestCase testcase) {
if ( "org.hibernate.spatial.integration.TestSpatialFunctions".equals( testcase.getClass().getCanonicalName() ) ) {
return TestData.fromFile( "db2/test-db2nozm-only-polygon.xml" );
}
return TestData.fromFile( "db2/test-db2nozm-data-set.xml" );
}
public DB2ExpectationsFactory createExpectationsFactory(DataSourceUtils dataSourceUtils) {
return new DB2ExpectationsFactory( dataSourceUtils );
}
@Override
public SQLExpressionTemplate getSQLExpressionTemplate() {
return new DB2ExpressionTemplate();
}
}

View File

@ -13,7 +13,7 @@ package org.hibernate.spatial.testing.dialects.h2geodb;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import org.hibernate.spatial.testing.GeometryEquality;
import org.hibernate.spatial.testing.JTSGeometryEquality;
/**
* Extends the test for {@link Geometry} equality, because GeoDB uses JTS
@ -23,7 +23,7 @@ import org.hibernate.spatial.testing.GeometryEquality;
* @deprecated This should no longer be necesseary
*/
@Deprecated
public class GeoDBGeometryEquality extends GeometryEquality {
public class GeoDBGeometryEquality extends JTSGeometryEquality {
@Override
public boolean test(Geometry geom1, Geometry geom2) {

View File

@ -13,7 +13,7 @@ import java.sql.SQLException;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.GeometryEquality;
import org.hibernate.spatial.testing.JTSGeometryEquality;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import org.hibernate.spatial.testing.TestData;
import org.hibernate.spatial.testing.TestSupport;
@ -43,7 +43,7 @@ public class GeoDBTestSupport extends TestSupport {
return TestData.fromFile( "h2geodb/test-geodb-data-set.xml" );
}
public GeometryEquality createGeometryEquality() {
public JTSGeometryEquality createGeometryEquality() {
return new GeoDBGeometryEquality();
}

View File

@ -10,13 +10,13 @@ package org.hibernate.spatial.testing.dialects.mysql;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import org.hibernate.spatial.testing.GeometryEquality;
import org.hibernate.spatial.testing.JTSGeometryEquality;
/**
* Extends the test for geometry equality, because
* MySQL stores empty geometries as NULL objects.
*/
public class MySQLGeometryEquality extends GeometryEquality {
public class MySQLGeometryEquality extends JTSGeometryEquality {
@Override
public boolean test(Geometry geom1, Geometry geom2) {

View File

@ -10,7 +10,7 @@ package org.hibernate.spatial.testing.dialects.mysql;
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.GeometryEquality;
import org.hibernate.spatial.testing.JTSGeometryEquality;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import org.hibernate.spatial.testing.TestData;
import org.hibernate.spatial.testing.TestSupport;
@ -34,7 +34,7 @@ public class MySQLTestSupport extends TestSupport {
}
@Override
public GeometryEquality createGeometryEquality() {
public JTSGeometryEquality createGeometryEquality() {
return new MySQLGeometryEquality();
}

View File

@ -0,0 +1,8 @@
EWKTReader doesn't work with the test data for Z or M data. It tests for 'POINTM' but the data is 'POINT M'.
TestSpatialFunctions failures:
transform:
DB2 transform functions between spatial reference systems with the same datum but not different datums.
This causes the transform test in TestSpatialFunctions to fail because it transforms from WGS84 to WGS_1972_Transit_Broadcast_Ephemeris

View File

@ -0,0 +1,67 @@
-- pagesize of 8k needed for enable_db operation
create database sample pagesize 8 k;
connect to sample;
-- spatially-enable the database; create spatial types, functions and stored procedures
!db2se enable_db sample;
-- create the spatial reference system for EPSG 4326 (WGS84)
-- this is the same as the Spatial Extender default srid 1003
!db2se drop_srs sample
-srsName EPSG4326
;
!db2se create_srs sample
-srsName EPSG4326
-srsId 4326
-coordsysName GCS_WGS_1984
-xOffset -180
-xScale 1000000
-yOffset -90
-zOffset 0
-zScale 1
-mOffset 0
-mScale 1
;
-- Create SQL function to return EWKT format from a geometry
create or replace function db2gse.asewkt(geometry db2gse.st_geometry)
returns clob(2G)
specific db2gse.asewkt1
language sql
deterministice
no external action
reads sql data
return 'srid=' || varchar(db2gse.st_srsid(geometry)) || ';' || db2gse.st_astext(geometry)
;
-- Create SQL function to create a geometry from EWKT format
create or replace function db2gse.geomfromewkt(instring varchar(32000))
returns db2gse.st_geometry
specific db2gse.fromewkt1
language sql
deterministic
no external action
reads sql data
return db2gse.st_geometry(
substr(instring,posstr(instring,';')+1, length(instring) - posstr(instring,';')),
integer(substr(instring,posstr(instring,'=')+1,posstr(instring,';')-(posstr(instring,'=')+1)))
)
;
-- Create a DB2 transform group to return and accept EWKT
CREATE TRANSFORM FOR db2gse.ST_Geometry EWKT (
FROM SQL WITH FUNCTION db2gse.asewkt(db2gse.ST_Geometry),
TO SQL WITH FUNCTION db2gse.geomfromewkt(varchar(32000)) )
;
-- Redefine the default DB2_PROGRAM to return and accept EWKT instead of WKT
DROP TRANSFORM DB2_PROGRAM FOR db2gse.ST_Geometry;
CREATE TRANSFORM FOR db2gse.ST_Geometry DB2_PROGRAM (
FROM SQL WITH FUNCTION db2gse.asewkt(db2gse.ST_Geometry),
TO SQL WITH FUNCTION db2gse.geomfromewkt(varchar(32000)) )
;
-- Give the test userid authority to create and access tables
grant dataaccess on database to hstest;

View File

@ -0,0 +1,188 @@
<TestData>
<Element>
<id>1</id>
<type>POINT</type>
<wkt>SRID=0;POINT(10 5)</wkt>
</Element>
<Element>
<id>2</id>
<type>POINT</type>
<wkt>SRID=4326;POINT(52.25 2.53)</wkt>
</Element>
<Element>
<id>4</id>
<type>POINT</type>
<wkt>SRID=4326;POINT ZM(10.0 2.0 1.0 3.0)</wkt>
</Element>
<Element>
<id>5</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING(10.0 5.0, 20.0 15.0)</wkt>
</Element>
<Element>
<id>6</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING(10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0)</wkt>
</Element>
<Element>
<id>7</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING Z(10.0 5.0 0.0, 20.0 15.0 3.0)</wkt>
</Element>
<Element>
<id>8</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING ZM(10.0 5.0 0.0 0.0, 20.0 15.0 3.0 1.0)</wkt>
</Element>
<Element>
<id>9</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING M(10.0 5.0 1, 20.0 15.0 2, 30.3 22.4 5, 10 30.0 2)</wkt>
</Element>
<Element>
<id>10</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING ZM(10.0 5.0 1 1, 20.0 15.0 2 3, 30.3 22.4 5 10, 10 30.0 2 12)</wkt>
</Element>
<Element>
<id>11</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0))</wkt>
</Element>
<Element>
<id>12</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING((10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0), (40.0 20.0, 42.0 18.0, 43.0 16.0, 40
14.0))
</wkt>
</Element>
<Element>
<id>13</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING Z((10.0 5.0 1.0, 20.0 15.0 2.0, 30.3 22.4 1.0, 10 30.0 1.0),(40.0 20.0 0.0, 42.0
18.0 1.0,
43.0 16.0 2.0, 40 14.0 3.0))
</wkt>
</Element>
<Element>
<id>14</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING ZM((10.0 5.0 1.0 0.0, 20.0 15.0 2.0 0.0, 30.3 22.4 1.0 1.0, 10 30.0 1.0
2.0),(40.0 20.0 0.0
3.0, 42.0 18.0 1.0 4.0, 43.0 16.0 2.0 5.0, 40 14.0 3.0 6.0))
</wkt>
</Element>
<Element>
<id>15</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING ZM((10.0 5.0 1.0 0.0, 20.0 15.0 2.0 0.0, 30.3 22.4 1.0 1.0, 10 30.0 1.0 2.0))
</wkt>
</Element>
<Element>
<id>16</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) )</wkt>
</Element>
<Element>
<id>17</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON Z( (0 0 0, 0 10 1, 10 10 1, 10 0 1, 0 0 0) )</wkt>
</Element>
<Element>
<id>18</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 5, 5 5,5 2, 2 2))</wkt>
</Element>
<Element>
<id>19</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON( (110 110, 110 120, 120 120, 120 110, 110 110) )</wkt>
</Element>
<Element>
<id>20</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=4326;MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 100, 120 140, 130 134, 105 100)) )</wkt>
</Element>
<Element>
<id>21</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=4326;MULTIPOLYGON Z( ((10 20 1, 30 40 2, 44 50 2, 10 20 1)), ((105 100 0, 120 140 10, 130 134 20, 105
100 0)) )
</wkt>
</Element>
<Element>
<id>22</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=4326;MULTIPOLYGON(( (0 0, 0 50, 50 50, 50 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10) ),((105 100,
120 140, 130
134, 105 100)) )
</wkt>
</Element>
<Element>
<id>26</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT(21 2)</wkt>
</Element>
<Element>
<id>27</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT Z(21 2 1, 25 5 2, 30 3 5)</wkt>
</Element>
<Element>
<id>28</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT ZM(21 2 1 0, 25 5 2 4, 30 3 5 2)</wkt>
</Element>
<Element>
<id>50</id>
<type>POINT</type>
<wkt>SRID=4326;POINT EMPTY</wkt>
</Element>
<Element>
<id>51</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING EMPTY</wkt>
</Element>
<Element>
<id>52</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON EMPTY</wkt>
</Element>
<Element>
<id>53</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT EMPTY</wkt>
</Element>
<Element>
<id>54</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING EMPTY</wkt>
</Element>
<Element>
<id>55</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=4326;MULTIPOLYGON EMPTY</wkt>
</Element>
</TestData>

View File

@ -0,0 +1,127 @@
<TestData>
<Element>
<id>1</id>
<type>POINT</type>
<wkt>SRID=4326;POINT(10 5)</wkt>
</Element>
<Element>
<id>2</id>
<type>POINT</type>
<wkt>SRID=4326;POINT(52.25 2.53)</wkt>
</Element>
<Element>
<id>5</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING(10.0 5.0, 20.0 15.0)</wkt>
</Element>
<Element>
<id>6</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING(10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0)</wkt>
</Element>
<Element>
<id>11</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0))</wkt>
</Element>
<Element>
<id>12</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING((10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0), (40.0 20.0, 42.0 18.0, 43.0 16.0, 40 14.0))
</wkt>
</Element>
<Element>
<id>16</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON( (0 0, 10 0, 10 10, 0 10, 0 0) )</wkt>
</Element>
<Element>
<id>18</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 5, 5 5, 5 2, 2 2))</wkt>
</Element>
<Element>
<id>19</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON( (110 110, 120 110, 120 120, 110 120, 110 110) )</wkt>
</Element>
<Element>
<id>20</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=4326;MULTIPOLYGON(((105 100, 130 134, 120 140, 105 100)), ((10 20, 44 50, 30 40, 10 20)))</wkt>
</Element>
<Element>
<id>22</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=4326;MULTIPOLYGON(((0 0, 50 0, 50 50, 0 50, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10)), ((105 100, 130 134, 120 140, 105 100)))
</wkt>
</Element>
<Element>
<id>50</id>
<type>POINT</type>
<wkt>SRID=4326;POINT EMPTY</wkt>
</Element>
<Element>
<id>51</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING EMPTY</wkt>
</Element>
<Element>
<id>52</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON EMPTY</wkt>
</Element>
<Element>
<id>53</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT EMPTY</wkt>
</Element>
<Element>
<id>54</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING EMPTY</wkt>
</Element>
<Element>
<id>55</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=4326;MULTIPOLYGON EMPTY</wkt>
</Element>
<!-- Z, M and ZM Geometries -->
<!-- Due to the default definition of the SRID in DB2, the M and Z values need to be whole integers -->
<Element>
<id>56</id>
<type>POINT</type>
<wkt>SRID=4326;POINT Z(4.23 50.32 10)</wkt>
</Element>
<Element>
<id>57</id>
<type>POINT</type>
<wkt>SRID=4326;POINT M(4.23 50.32 10)</wkt>
</Element>
<Element>
<id>58</id>
<type>POINT</type>
<wkt>SRID=4326;POINT ZM(4.23 50.32 5 10)</wkt>
</Element>
</TestData>

View File

@ -0,0 +1,46 @@
<TestData>
<Element>
<id>16</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON( (0 0, 10 0, 10 10, 0 10, 0 0) )</wkt>
</Element>
<Element>
<id>18</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 5, 5 5, 5 2, 2 2))</wkt>
</Element>
<Element>
<id>19</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON( (110 110, 120 110, 120 120, 110 120, 110 110) )</wkt>
</Element>
<Element>
<id>20</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=4326;MULTIPOLYGON(((105 100, 130 134, 120 140, 105 100)), ((10 20, 44 50, 30 40, 10 20)))</wkt>
</Element>
<Element>
<id>22</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=4326;MULTIPOLYGON(((0 0, 50 0, 50 50, 0 50, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10)), ((105 100, 130 134, 120 140, 105 100)))
</wkt>
</Element>
<Element>
<id>52</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON EMPTY</wkt>
</Element>
<Element>
<id>55</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=4326;MULTIPOLYGON EMPTY</wkt>
</Element>
</TestData>

View File

@ -107,3 +107,13 @@ hibernate.connection.password @jdbc.pass@
#hibernate.connection.url jdbc:sap://localhost:30015
#hibernate.connection.username HIBERNATE_TEST
#hibernate.connection.password H1bernate_test
##
## DB2 dialect
##
#hibernate.dialect org.hibernate.spatial.dialect.db2.DB2SpatialDialect
#hibernate.connection.driver_class com.ibm.db2.jcc.DB2Driver
#hibernate.connection.url jdbc:db2://localhost:50000/hibern8
#hibernate.spatial.db2.srid 4326
#hibernate.connection.username db2inst1
#hibernate.connection.password dbinst1-pwd