Fix Hibernate Spatial test on SAP HANA

This commit is contained in:
Jonathan Bregler 2017-10-09 09:36:35 +02:00 committed by Steve Ebersole
parent 54b506ecf4
commit 8de0f9e2a1
14 changed files with 285 additions and 158 deletions

View File

@ -25,14 +25,18 @@ public class HANAGeometryTypeDescriptor implements SqlTypeDescriptor {
private static final long serialVersionUID = -6978798264716544804L;
/**
* An instance of the descrtiptor
*/
public static final HANAGeometryTypeDescriptor INSTANCE = new HANAGeometryTypeDescriptor();
public static final HANAGeometryTypeDescriptor CRS_LOADING_INSTANCE = new HANAGeometryTypeDescriptor( true );
public static final HANAGeometryTypeDescriptor INSTANCE = new HANAGeometryTypeDescriptor( false );
final boolean determineCrsIdFromDatabase;
public HANAGeometryTypeDescriptor(boolean determineCrsIdFromDatabase) {
this.determineCrsIdFromDatabase = determineCrsIdFromDatabase;
}
@Override
public int getSqlType() {
return Types.ARRAY;
return Types.OTHER;
}
@Override
@ -67,8 +71,13 @@ public class HANAGeometryTypeDescriptor implements SqlTypeDescriptor {
@Override
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
if ( HANAGeometryTypeDescriptor.this.determineCrsIdFromDatabase ) {
return getJavaDescriptor().wrap( HANASpatialUtils.toGeometry( rs, name ), options );
}
else {
return getJavaDescriptor().wrap( HANASpatialUtils.toGeometry( rs.getObject( name ) ), options );
}
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {

View File

@ -8,6 +8,8 @@ package org.hibernate.spatial.dialect.hana;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.HANAColumnStoreDialect;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.ConfigurationService.Converter;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.JTSGeometryType;
@ -21,6 +23,8 @@ public class HANASpatialDialect extends HANAColumnStoreDialect implements Spatia
private static final long serialVersionUID = -432631517465714911L;
private static final String DETERMINE_CRS_ID_FROM_DATABASE_PARAMETER_NAME = "hibernate.spatial.dialect.hana.determine_crs_id_from_database";
public HANASpatialDialect() {
registerColumnType( HANAGeometryTypeDescriptor.INSTANCE.getSqlType(), "ST_GEOMETRY" );
registerColumnType( HANAPointTypeDescriptor.INSTANCE.getSqlType(), "ST_POINT" );
@ -62,7 +66,7 @@ public class HANASpatialDialect extends HANAColumnStoreDialect implements Spatia
registerFunction( SpatialFunction.overlaps.name(),
new HANASpatialFunction( "ST_Overlaps", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
registerFunction( SpatialFunction.relate.name(),
new HANASpatialFunction( "ST_Relate", StandardBasicTypes.INTEGER, true ) );
new HANASpatialFunction( "ST_Relate", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
registerFunction( SpatialFunction.srid.name(),
new HANASpatialFunction( "ST_SRID", StandardBasicTypes.INTEGER, false ) );
registerFunction( SpatialFunction.symdifference.name(), new HANASpatialFunction( "ST_SymDifference", true ) );
@ -102,10 +106,31 @@ public class HANASpatialDialect extends HANAColumnStoreDialect implements Spatia
@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes( typeContributions, serviceRegistry );
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
boolean determineCrsIdFromDatabase = configurationService.getSetting(
DETERMINE_CRS_ID_FROM_DATABASE_PARAMETER_NAME,
new Converter<Boolean>() {
@Override
public Boolean convert(Object value) {
return Boolean.valueOf( value.toString() );
}
},
Boolean.FALSE ).booleanValue();
if ( determineCrsIdFromDatabase ) {
typeContributions.contributeType( new GeolatteGeometryType( HANAGeometryTypeDescriptor.CRS_LOADING_INSTANCE ) );
typeContributions.contributeType( new JTSGeometryType( HANAGeometryTypeDescriptor.CRS_LOADING_INSTANCE ) );
}
else {
typeContributions.contributeType( new GeolatteGeometryType( HANAGeometryTypeDescriptor.INSTANCE ) );
typeContributions.contributeType( new JTSGeometryType( HANAGeometryTypeDescriptor.INSTANCE ) );
}
}
@Override
public String getSpatialFilterExpression(String columnName) {
return columnName + ".ST_IntersectsFilter(ST_GeomFromEWKB(?)) = 1";
@ -203,5 +228,4 @@ public class HANASpatialDialect extends HANAColumnStoreDialect implements Spatia
}
return false;
}
}

View File

@ -14,6 +14,8 @@ import org.hibernate.type.Type;
public class HANASpatialFunction extends StandardSQLFunction {
private static final String AS_EWKB_SUFFIX = ".ST_AsEWKB()";
private final boolean firstArgumentIsGeometryType;
public HANASpatialFunction(String name, boolean firstArgumentIsGeometryType) {
@ -33,14 +35,22 @@ public class HANASpatialFunction extends StandardSQLFunction {
}
else {
final StringBuilder buf = new StringBuilder();
buf.append( arguments.get( 0 ) ).append( "." ).append( getName() ).append( '(' );
// If the first argument is an expression, e.g. a nested function, strip the .ST_AsEWKB() suffix
buf.append( stripEWKBSuffix( arguments.get( 0 ) ) );
// Add function call
buf.append( "." ).append( getName() ).append( '(' );
// Add function arguments
for ( int i = 1; i < arguments.size(); i++ ) {
final Object argument = arguments.get( i );
final boolean parseFromWKB = this.firstArgumentIsGeometryType && i == 1 && "?".equals( argument );
// Check if first argument needs to be parsed from EWKB. This is the case if the first argument is a
// parameter that is set as EWKB or if it's a nested function call.
final boolean parseFromWKB = ( this.firstArgumentIsGeometryType && i == 1 && "?".equals( argument ) );
if ( parseFromWKB ) {
buf.append( "ST_GeomFromEWKB(" );
}
buf.append( argument );
buf.append( stripEWKBSuffix( argument ) );
if ( parseFromWKB ) {
buf.append( ")" );
}
@ -49,7 +59,20 @@ public class HANASpatialFunction extends StandardSQLFunction {
}
}
buf.append( ')' );
// If it doesn't specify an explicit type, assume it's a geometry
if ( this.getType() == null ) {
buf.append( AS_EWKB_SUFFIX );
}
return buf.toString();
}
}
private Object stripEWKBSuffix(Object argument) {
if ( ( argument instanceof String ) && ( (String) argument ).endsWith( AS_EWKB_SUFFIX ) ) {
String argumentString = (String) argument;
return argumentString.substring( 0, argumentString.length() - AS_EWKB_SUFFIX.length() );
}
return argument;
}
}

View File

@ -7,6 +7,9 @@
package org.hibernate.spatial.dialect.hana;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.geolatte.geom.ByteBuffer;
@ -18,7 +21,95 @@ import org.geolatte.geom.codec.WkbEncoder;
public class HANASpatialUtils {
private static final int POSTGIS_SRID_FLAG = 0x20000000;
@SuppressWarnings("resource")
public static Geometry<?> toGeometry(ResultSet rs, String name) throws SQLException {
ByteBuffer buffer = toByteBuffer( rs.getObject( name ) );
if ( buffer == null ) {
return null;
}
// Get table and column names from the result set metadata
String tableName = null;
String columnName = null;
for ( int i = 1; i <= rs.getMetaData().getColumnCount(); i++ ) {
if ( name.equals( rs.getMetaData().getColumnLabel( i ) ) || name.toUpperCase().equals( rs.getMetaData().getColumnLabel( i ) ) ) {
tableName = rs.getMetaData().getTableName( i );
columnName = rs.getMetaData().getColumnName( i );
}
}
assert tableName != null;
assert columnName != null;
// no table and/or column names found (
if ( tableName.isEmpty() || columnName.isEmpty() ) {
return toGeometry( buffer );
}
byte orderByte = buffer.get();
int typeCode = (int) buffer.getUInt();
Connection connection = rs.getStatement().getConnection();
// Check if SRID is set
if ( ( typeCode & POSTGIS_SRID_FLAG ) != POSTGIS_SRID_FLAG ) {
// No SRID set => try to get SRID from the database
try ( PreparedStatement psSrid = connection
.prepareStatement( "SELECT SRS_ID FROM SYS.ST_GEOMETRY_COLUMNS WHERE SCHEMA_NAME=CURRENT_SCHEMA AND TABLE_NAME=? AND COLUMN_NAME=?" ) ) {
psSrid.setString( 1, tableName );
psSrid.setString( 2, columnName );
try ( ResultSet rsSrid = psSrid.executeQuery() ) {
if ( rsSrid.next() ) {
int crsId = rsSrid.getInt( 1 );
buffer = addCrsId( buffer.toByteArray(), orderByte, typeCode, crsId );
}
else {
// ignore
}
}
}
}
return toGeometry( buffer );
}
private static ByteBuffer addCrsId(byte[] wkb, byte orderByte, int typeCode, int crsId) {
ByteBuffer buffer = ByteBuffer.allocate( wkb.length + 4 ); // original capacity + 4 bytes for the CRS ID
buffer.setByteOrder( ByteOrder.valueOf( orderByte ) );
buffer.put( orderByte ); // write byte order
buffer.putUInt( typeCode | POSTGIS_SRID_FLAG ); // set SRID flag
buffer.putInt( crsId ); // write CRS ID
// write remaining data
for ( int i = 5; i < wkb.length; i++ ) {
buffer.put( wkb[i] );
}
buffer.rewind();
return buffer;
}
public static Geometry<?> toGeometry(Object obj) {
return toGeometry( toByteBuffer( obj ) );
}
private static Geometry<?> toGeometry(ByteBuffer buffer) {
if ( buffer == null ) {
return null;
}
WkbDecoder decoder = Wkb.newDecoder( Wkb.Dialect.HANA_EWKB );
return decoder.decode( buffer );
}
private static ByteBuffer toByteBuffer(Object obj) {
byte[] raw = null;
if ( obj == null ) {
return null;
@ -34,9 +125,8 @@ public class HANASpatialUtils {
}
ByteBuffer buffer = ByteBuffer.from( raw );
WkbDecoder decoder = Wkb.newDecoder( Wkb.Dialect.HANA_EWKB );
return decoder.decode( buffer );
buffer.setByteOrder( ByteOrder.valueOf( raw[0] ) );
return buffer;
}
private static byte[] toByteArray(Blob blob) {

View File

@ -21,6 +21,7 @@ import org.hibernate.Transaction;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.dialect.h2geodb.GeoDBDialect;
import org.hibernate.spatial.dialect.hana.HANASpatialDialect;
import org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect;
import org.hibernate.spatial.testing.SpatialDialectMatcher;
import org.hibernate.spatial.testing.SpatialFunctionalTestCase;
@ -239,7 +240,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Boolean> dbexpected = expectationsFactory.getWithin( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, within(geom, :filter) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where within(geom, :filter) = true and srid(geom) = 4326", pckg
"where within(geom, :filter) = true and srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -262,7 +263,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Boolean> dbexpected = expectationsFactory.getEquals( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, equals(geom, :filter) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where equals(geom, :filter) = true and srid(geom) = 4326", pckg
"where equals(geom, :filter) = true and srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -285,7 +286,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Boolean> dbexpected = expectationsFactory.getCrosses( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, crosses(geom, :filter) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where crosses(geom, :filter) = true and srid(geom) = 4326", pckg
"where crosses(geom, :filter) = true and srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -309,7 +310,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Boolean> dbexpected = expectationsFactory.getContains( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, contains(geom, :filter) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where contains(geom, :filter) = true and srid(geom) = 4326", pckg
"where contains(geom, :filter) = true and srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -332,7 +333,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Boolean> dbexpected = expectationsFactory.getDisjoint( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, disjoint(geom, :filter) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where disjoint(geom, :filter) = true and srid(geom) = 4326", pckg
"where disjoint(geom, :filter) = true and srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -355,7 +356,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Boolean> dbexpected = expectationsFactory.getIntersects( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, intersects(geom, :filter) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where intersects(geom, :filter) = true and srid(geom) = 4326", pckg
"where intersects(geom, :filter) = true and srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -378,7 +379,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Boolean> dbexpected = expectationsFactory.getOverlaps( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, overlaps(geom, :filter) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where overlaps(geom, :filter) = true and srid(geom) = 4326", pckg
"where overlaps(geom, :filter) = true and srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -400,7 +401,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
}
String hql = format(
"SELECT id, touches(geom, :filter) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where touches(geom, :filter) = true and srid(geom) = 4326", pckg
"where touches(geom, :filter) = true and srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<Integer, Boolean> dbexpected = expectationsFactory.getTouches( expectationsFactory.getTestPolygon() );
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPolygon() );
@ -428,7 +429,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
);
String hql = format(
"SELECT id, relate(geom, :filter, :matrix) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where relate(geom, :filter, :matrix) = true and srid(geom) = 4326", pckg
"where relate(geom, :filter, :matrix) = true and srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPolygon() );
params.put( "matrix", matrix );
@ -458,7 +459,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Double> dbexpected = expectationsFactory.getDistance( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, distance(geom, :filter) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where srid(geom) = 4326", pckg
"where srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -481,7 +482,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Geometry> dbexpected = expectationsFactory.getBuffer( Double.valueOf( 1.0 ) );
String hql = format(
"SELECT id, buffer(geom, :distance) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where srid(geom) = 4326", pckg
"where srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "distance", Double.valueOf( 1.0 ) );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -511,7 +512,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Geometry> dbexpected = expectationsFactory.getConvexHull( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, convexhull(geomunion(geom, :polygon)) from org.hibernate.spatial.integration" +
".%s.GeomEntity where srid(geom) = 4326", pckg
".%s.GeomEntity where srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "polygon", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -539,7 +540,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Geometry> dbexpected = expectationsFactory.getIntersection( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, intersection(geom, :polygon) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where srid(geom) = 4326", pckg
"where srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "polygon", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -562,7 +563,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Geometry> dbexpected = expectationsFactory.getDifference( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, difference(geom, :polygon) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where srid(geom) = 4326", pckg
"where srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "polygon", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -585,7 +586,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Geometry> dbexpected = expectationsFactory.getSymDifference( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, symdifference(geom, :polygon) from " +
"org.hibernate.spatial.integration.%s.GeomEntity where srid(geom) = 4326", pckg
"org.hibernate.spatial.integration.%s.GeomEntity where srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "polygon", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -608,7 +609,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Geometry> dbexpected = expectationsFactory.getGeomUnion( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, geomunion(geom, :polygon) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where srid(geom) = 4326", pckg
"where srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "polygon", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
@ -636,13 +637,13 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
String hql = format(
"SELECT id, dwithin(geom, :filter, :distance) from " +
"org.hibernate.spatial.integration.%s.GeomEntity where dwithin(geom, :filter, :distance) = true " +
"and srid(geom) = 4326", pckg
"and srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPoint() );
if ( getDialect() instanceof OracleSpatial10gDialect ) {
//because this uses the weird syntax and conventions of SDO_WITHIN_DISTANCE which returns a string (really)
// we use a different boolean expression guaranteed to be true, and we set the third parameter to key/value string
hql = "SELECT id, issimple(geom) from org.hibernate.spatial.integration.GeomEntity where dwithin(geom, :filter, :distance) = true and srid(geom) = 4326";
hql = "SELECT id, issimple(geom) from org.hibernate.spatial.integration.GeomEntity where dwithin(geom, :filter, :distance) = true and srid(geom) = " + expectationsFactory.getTestSrid();
params.put( "distance", "distance = 30" );
}
else {
@ -651,12 +652,16 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
}
// The transform tests are skipped for HANA because there is no transform definition for SRID 0
@Test
@SkipForDialect(value = HANASpatialDialect.class)
public void test_transform_on_jts() throws SQLException {
transform( JTS );
}
@Test
@SkipForDialect(value = HANASpatialDialect.class)
public void test_transform_on_geolatte() throws SQLException {
transform( GEOLATTE );
}
@ -669,7 +674,7 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase {
Map<Integer, Geometry> dbexpected = expectationsFactory.getTransform( epsg );
String hql = format(
"SELECT id, transform(geom, :epsg) from org.hibernate.spatial.integration.%s.GeomEntity " +
"where srid(geom) = 4326", pckg
"where srid(geom) = %d", pckg, expectationsFactory.getTestSrid()
);
Map<String, Object> params = createQueryParams( "epsg", Integer.valueOf( epsg ) );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );

View File

@ -11,6 +11,8 @@ 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.testing.TestDataElement;
import org.geolatte.geom.Geometry;
@ -60,8 +62,14 @@ public class GeomEntity {
this.geom = geom;
}
public static GeomEntity createFrom(TestDataElement element) throws WktDecodeException {
WktDecoder decoder = Wkt.newDecoder( Wkt.Dialect.POSTGIS_EWKT_1 );
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 );

View File

@ -23,6 +23,7 @@ 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.testing.SpatialDialectMatcher;
import org.hibernate.spatial.testing.SpatialFunctionalTestCase;
@ -115,12 +116,14 @@ public class TestStoreRetrieveUsingGeolatte extends SpatialFunctionalTestCase {
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 );
;
GeomEntity entity = GeomEntity.createFrom( element, dialect );
stored.put( entity.getId(), entity );
session.save( entity );
tx.commit();

View File

@ -16,7 +16,8 @@ import com.vividsolutions.jts.io.ParseException;
import org.geolatte.geom.codec.Wkt;
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.testing.TestDataElement;
/**
@ -58,8 +59,14 @@ public class GeomEntity {
this.geom = geom;
}
public static GeomEntity createFrom(TestDataElement element) throws ParseException {
WktDecoder decoder = Wkt.newDecoder( Wkt.Dialect.POSTGIS_EWKT_1 );
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 );
}
Geometry geom = JTS.to( decoder.decode( element.wkt ) );
GeomEntity result = new GeomEntity();
result.setId( element.id );

View File

@ -20,6 +20,7 @@ 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.testing.SpatialDialectMatcher;
import org.hibernate.spatial.testing.SpatialFunctionalTestCase;
@ -112,12 +113,13 @@ public class TestStoreRetrieveUsingJTS extends SpatialFunctionalTestCase {
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 );
GeomEntity entity = GeomEntity.createFrom( element, dialect );
stored.put( entity.getId(), entity );
session.save( entity );
tx.commit();

View File

@ -1,28 +0,0 @@
package org.hibernate.spatial.testing.dialects.hana;
import java.sql.SQLException;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
public class HANADataSourceUtils extends DataSourceUtils {
public HANADataSourceUtils(String jdbcDriver, String jdbcUrl, String jdbcUser, String jdbcPass,
SQLExpressionTemplate sqlExpressionTemplate) {
super(jdbcDriver, jdbcUrl, jdbcUser, jdbcPass, sqlExpressionTemplate);
}
public HANADataSourceUtils(String propertyFile, SQLExpressionTemplate template) {
super(propertyFile, template);
}
@Override
public void afterCreateSchema() {
try {
executeStatement("ALTER TABLE GEOMTEST DROP (GEOM)");
executeStatement("ALTER TABLE GEOMTEST ADD (GEOM ST_GEOMETRY(4326))");
}
catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -33,42 +33,42 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
@Override
protected NativeSQLStatement createNativeBufferStatement(Double distance) {
return createNativeSQLStatement(
"select t.id, t.geom.ST_Buffer(?) from GeomTest t where t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Buffer(?) from GeomTest t where t.geom.ST_SRID() = " + getTestSrid(),
new Object[] { distance });
}
@Override
protected NativeSQLStatement createNativeConvexHullStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Union(ST_GeomFromText(?, 0)).ST_ConvexHull().ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Union(ST_GeomFromText(?, " + getTestSrid() + ")).ST_ConvexHull().ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeIntersectionStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Intersection(ST_GeomFromText(?, 0)).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Intersection(ST_GeomFromText(?, " + getTestSrid() + ")).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeDifferenceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Difference(ST_GeomFromText(?, 0)).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Difference(ST_GeomFromText(?, " + getTestSrid() + ")).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeSymDifferenceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_SymDifference(ST_GeomFromText(?, 0)).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_SymDifference(ST_GeomFromText(?, " + getTestSrid() + ")).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeGeomUnionStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Union(ST_GeomFromText(?, 0)).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Union(ST_GeomFromText(?, " + getTestSrid() + ")).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@ -128,42 +128,42 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
@Override
protected NativeSQLStatement createNativeWithinStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Within(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Within(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Within(ST_GeomFromText(?, " + getTestSrid() + ")) from GeomTest t where t.geom.ST_Within(ST_GeomFromText(?, " + getTestSrid() + ")) = 1 and t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeEqualsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Equals(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Equals(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Equals(ST_GeomFromText(?, " + getTestSrid() + ")) from GeomTest t where t.geom.ST_Equals(ST_GeomFromText(?, " + getTestSrid() + ")) = 1 and t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeCrossesStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Crosses(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Crosses(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Crosses(ST_GeomFromText(?, " + getTestSrid() + ")) from GeomTest t where t.geom.ST_Crosses(ST_GeomFromText(?, " + getTestSrid() + ")) = 1 and t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeContainsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Contains(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Contains(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Contains(ST_GeomFromText(?, " + getTestSrid() + ")) from GeomTest t where t.geom.ST_Contains(ST_GeomFromText(?, " + getTestSrid() + ")) = 1 and t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeDisjointStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Disjoint(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Disjoint(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Disjoint(ST_GeomFromText(?, " + getTestSrid() + ")) from GeomTest t where t.geom.ST_Disjoint(ST_GeomFromText(?, " + getTestSrid() + ")) = 1 and t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeTransformStatement(int epsg) {
return createNativeSQLStatement(
"select t.id, t.geom.ST_Transform(" + epsg + ") from GeomTest t where t.geom.ST_SRID() = 0");
"select t.id, t.geom.ST_Transform(" + epsg + ") from GeomTest t where t.geom.ST_SRID() = " + getTestSrid());
}
@Override
@ -174,63 +174,58 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
@Override
protected NativeSQLStatement createNativeIntersectsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Intersects(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Intersects(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Intersects(ST_GeomFromText(?, " + getTestSrid() + ")) from GeomTest t where t.geom.ST_Intersects(ST_GeomFromText(?, " + getTestSrid() + ")) = 1 and t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeFilterStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_IntersectsFilter(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_IntersectsFilter(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_IntersectsFilter(ST_GeomFromText(?, " + getTestSrid() + ")) from GeomTest t where t.geom.ST_IntersectsFilter(ST_GeomFromText(?, " + getTestSrid() + ")) = 1 and t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeTouchesStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Touches(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Touches(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Touches(ST_GeomFromText(?, " + getTestSrid() + ")) from GeomTest t where t.geom.ST_Touches(ST_GeomFromText(?, " + getTestSrid() + ")) = 1 and t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeOverlapsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Overlaps(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Overlaps(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Overlaps(ST_GeomFromText(?, " + getTestSrid() + ")) from GeomTest t where t.geom.ST_Overlaps(ST_GeomFromText(?, " + getTestSrid() + ")) = 1 and t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
protected NativeSQLStatement createNativeRelateStatement(Geometry geom, String matrix) {
String sql = "select t.id, t.geom.ST_Relate(ST_GeomFromText(?, 0), '" + matrix
+ "' ) from GeomTest t where t.geom.ST_Relate(ST_GeomFromText(?, 0), '" + matrix
+ "') = 1 and t.geom.ST_SRID() = 0";
String sql = "select t.id, t.geom.ST_Relate(ST_GeomFromText(?, " + getTestSrid() + "), '" + matrix
+ "' ) from GeomTest t where t.geom.ST_Relate(ST_GeomFromText(?, " + getTestSrid() + "), '" + matrix
+ "') = 1 and t.geom.ST_SRID() = " + getTestSrid();
return createNativeSQLStatementAllWKTParams(sql, geom.toText());
}
@Override
protected NativeSQLStatement createNativeDwithinStatement(Point geom, double distance) {
return createNativeSQLStatementAllWKTParams("select t.id, t.geom.ST_WithinDistance(ST_GeomFromText(?, 0), "
+ distance + ") from GeomTest t where t.geom.ST_WithinDistance(ST_GeomFromText(?, 0), " + distance
+ ") = 1 and t.geom.ST_SRID() = 0", geom.toText());
return createNativeSQLStatementAllWKTParams("select t.id, t.geom.ST_WithinDistance(ST_GeomFromText(?, " + getTestSrid() + "), "
+ distance + ") from GeomTest t where t.geom.ST_WithinDistance(ST_GeomFromText(?, " + getTestSrid() + "), " + distance
+ ") = 1 and t.geom.ST_SRID() = " + getTestSrid(), geom.toText());
}
@Override
protected NativeSQLStatement createNativeDistanceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Distance(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_SRID() = 0",
"select t.id, t.geom.ST_Distance(ST_GeomFromText(?, " + getTestSrid() + ")) from GeomTest t where t.geom.ST_SRID() = " + getTestSrid(),
geom.toText());
}
@Override
public int getTestSrid() {
return 0;
}
@Override
public Polygon getTestPolygon() {
WKTReader reader = new WKTReader();
try {
Polygon polygon = (Polygon) reader.read( "POLYGON((0 0, 50 0, 90 90, 0 100, 0 0))" );
Polygon polygon = (Polygon) reader.read( "POLYGON((0 0, 50 0, 90 90, 100 0, 0 0))" );
polygon.setSRID( getTestSrid() );
return polygon;
}
@ -239,4 +234,9 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
}
}
@Override
public int getTestSrid() {
return 0;
}
}

View File

@ -16,7 +16,7 @@ import org.hibernate.spatial.testing.WktUtility;
*/
public class HANAExpressionTemplate implements SQLExpressionTemplate {
static final String SQL_TEMPLATE = "insert into geomtest (id, type, geom) values (%d, '%s', ST_GeomFromText('%s', %d).ST_SRID(4326))";
static final String SQL_TEMPLATE = "insert into geomtest (id, type, geom) values (%d, '%s', ST_GeomFromText('%s', %d))";
@Override
public String toInsertSql(TestDataElement testDataElement) {

View File

@ -7,7 +7,6 @@
package org.hibernate.spatial.testing.dialects.hana;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import org.hibernate.spatial.testing.TestData;
@ -31,9 +30,4 @@ public class HANATestSupport extends TestSupport {
return new HANAExpressionTemplate();
}
@Override
public DataSourceUtils createDataSourceUtil(ServiceRegistry serviceRegistry) {
super.createDataSourceUtil(serviceRegistry);
return new HANADataSourceUtils( driver(), url(), user(), passwd(), getSQLExpressionTemplate() );
}
}

View File

@ -18,76 +18,75 @@
<Element>
<id>2</id>
<type>POINT</type>
<wkt>SRID=4326;POINT(52.25 2.53)</wkt>
<wkt>POINT(52.25 2.75)</wkt>
</Element>
<Element>
<id>3</id>
<type>POINT</type>
<!-- <wkt>SRID=4326;POINT(150000 200000)</wkt> -->
<wkt>SRID=4326;POINT(15 20)</wkt>
<wkt>POINT(150000 200000)</wkt>
</Element>
<Element>
<id>4</id>
<type>POINT</type>
<wkt>SRID=4326;POINT ZM(10.0 2.0 1.0 3.0)</wkt>
<wkt>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>
<wkt>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>
<wkt>LINESTRING(10.0 5.0, 20.0 15.0, 30.25 22.375, 10 30.0)</wkt>
</Element>
<Element>
<id>7</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING M(10.0 5.0 0.0, 20.0 15.0 3.0)</wkt>
<wkt>LINESTRING M(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>
<wkt>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>
<wkt>LINESTRING M(10.0 5.0 1, 20.0 15.0 2, 30.25 22.375 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>
<wkt>LINESTRING ZM(10.0 5.0 1 1, 20.0 15.0 2 3, 30.25 22.375 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>
<wkt>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>MULTILINESTRING((10.0 5.0, 20.0 15.0, 30.25 22.375, 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 M((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,
<wkt>MULTILINESTRING M((10.0 5.0 1.0, 20.0 15.0 2.0, 30.25 22.375 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>
@ -95,7 +94,7 @@
<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
<wkt>MULTILINESTRING ZM((10.0 5.0 1.0 0.0, 20.0 15.0 2.0 0.0, 30.25 22.375 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>
@ -103,137 +102,128 @@
<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>
<wkt>MULTILINESTRING ZM((10.0 5.0 1.0 0.0, 20.0 15.0 2.0 0.0, 30.25 22.375 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>
<wkt>POLYGON( (0 0, 10 0, 10 10, 0 10, 0 0) )</wkt>
</Element>
<Element>
<id>17</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON M( (0 0 0, 0 10 1, 10 10 1, 10 0 1, 0 0 0) )</wkt>
<wkt>POLYGON M( (0 0 0, 10 0 1, 10 10 1, 0 10 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>
<wkt>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, 110 120, 120 120, 120 110, 110 110) )</wkt> -->
<wkt>SRID=4326;POLYGON( (11 11, 11 12, 12 12, 12 11, 11 11) )</wkt>
<wkt>POLYGON( (110 110, 120 110, 120 120, 110 120, 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> -->
<wkt>SRID=4326;MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 10, 120 14, 130 13.4, 105 10)) )</wkt>
<wkt>MULTIPOLYGON( ((10 20, 44 50, 30 40, 10 20)), ((105 100, 130 134, 120 140, 105 100)) )</wkt>
</Element>
<Element>
<id>21</id>
<type>MULTIPOLYGON</type>
<!-- <wkt>SRID=4326;MULTIPOLYGON M( ((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>SRID=4326;MULTIPOLYGON M( ((10 20 1, 30 40 2, 44 50 2, 10 20 1)), ((105 10 0, 120 14 10, 130 13.4 20, 105 10 0)) )
<wkt>MULTIPOLYGON M( ((10 20 1, 44 50 2, 30 40 2, 10 20 1)), ((105 100 0, 130 134 20, 120 140 10, 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> -->
<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 10, 120 14, 130
13.4, 105 10)) )
<wkt>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>25</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT(21 2, 25 5, 30 3)</wkt>
<wkt>MULTIPOINT(21 2, 25 5, 30 3)</wkt>
</Element>
<Element>
<id>26</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT(21 2)</wkt>
<wkt>MULTIPOINT(21 2)</wkt>
</Element>
<Element>
<id>27</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT M(21 2 1, 25 5 2, 30 3 5)</wkt>
<wkt>MULTIPOINT M(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>
<wkt>MULTIPOINT ZM(21 2 1 0, 25 5 2 4, 30 3 5 2)</wkt>
</Element>
<Element>
<id>30</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3))</wkt>
<wkt>GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>31</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0)))</wkt>
<wkt>GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0)))</wkt>
</Element>
<Element>
<id>32</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0),(1 1, 2 1, 2 2, 1 2,
<wkt>GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0),(1 1, 1 2, 2 2, 2 1,
1 1)))
</wkt>
</Element>
<Element>
<id>33</id>
<type>GEOMETRYCOLLECTION</type>
<!-- <wkt>SRID=4326;GEOMETRYCOLLECTION( MULTIPOINT(21 2, 25 5, 30 3), MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 100, -->
<!-- 120 140, 130 134, 105 100)) ), MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0))) -->
<!-- </wkt> -->
<wkt>SRID=4326;GEOMETRYCOLLECTION( MULTIPOINT(21 2, 25 5, 30 3), MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 10,
120 14, 130 13.4, 105 10)) ), MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0)))
<wkt>GEOMETRYCOLLECTION( MULTIPOINT(21 2, 25 5, 30 3), MULTIPOLYGON( ((10 20, 44 50, 30 40, 10 20)), ((105 100,
130 134, 120 140, 105 100)) ), MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0)))
</wkt>
</Element>
<Element>
<id>34</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), POINT EMPTY, LINESTRING(4 2, 5 3))</wkt>
<wkt>GEOMETRYCOLLECTION(POINT(4 0), POINT EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>35</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING EMPTY, LINESTRING(4 2, 5 3))</wkt>
<wkt>GEOMETRYCOLLECTION(POINT(4 0), LINESTRING EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>36</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), GEOMETRYCOLLECTION EMPTY, LINESTRING(4 2, 5 3))</wkt>
<wkt>GEOMETRYCOLLECTION(POINT(4 0), GEOMETRYCOLLECTION EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>37</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), POLYGON EMPTY, LINESTRING(4 2, 5 3))</wkt>
<wkt>GEOMETRYCOLLECTION(POINT(4 0), POLYGON EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>38</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), MULTILINESTRING EMPTY, LINESTRING(4 2, 5 3))</wkt>
<wkt>GEOMETRYCOLLECTION(POINT(4 0), MULTILINESTRING EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>39</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), MULTIPOINT EMPTY, LINESTRING(4 2, 5 3))</wkt>
<wkt>GEOMETRYCOLLECTION(POINT(4 0), MULTIPOINT EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>40</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), MULTIPOLYGON EMPTY, LINESTRING(4 2, 5 3))</wkt>
<wkt>GEOMETRYCOLLECTION(POINT(4 0), MULTIPOLYGON EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>