HHH-14803 Upgrade MariaDB Spatial support

This commit is contained in:
Karel Maesen 2021-10-30 18:51:16 +02:00
parent a7167e2a48
commit 0636f1de14
30 changed files with 362 additions and 403 deletions

View File

@ -41,7 +41,7 @@ sourceSets.test.resources {
}
tasks.test {
enabled = ['pgsql', 'cockroachdb'].contains( project.db )
enabled = ['pgsql', 'cockroachdb', 'mariadb'].contains( project.db )
}
tasks.test.include '**/*'

View File

@ -0,0 +1,63 @@
/*
* 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, 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;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.query.sqm.function.NamedSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.type.BasicTypeRegistry;
public class BaseSqmFunctionDescriptors implements KeyedSqmFunctionDescriptors {
protected final Map<FunctionKey, SqmFunctionDescriptor> map = new HashMap<>();
public BaseSqmFunctionDescriptors(FunctionContributions functionContributions) {
final BasicTypeRegistry basicTypeRegistry = functionContributions.getTypeConfiguration().getBasicTypeRegistry();
for ( CommonSpatialFunction func : filter( CommonSpatialFunction.values() ) ) {
final FunctionReturnTypeResolver returnTypeResolver;
if ( func.getReturnType() == null ) {
returnTypeResolver = null;
}
else {
returnTypeResolver = StandardFunctionReturnTypeResolvers.invariant(
basicTypeRegistry.resolve( func.getReturnType() )
);
}
map.put(
func.getKey(),
new NamedSqmFunctionDescriptor(
func.getKey().getName(),
true,
StandardArgumentsValidators.exactly( func.getNumArgs() ),
returnTypeResolver
)
);
}
}
public CommonSpatialFunction[] filter(CommonSpatialFunction[] functions) {
return functions;
}
public Map<FunctionKey, SqmFunctionDescriptor> asMap() {
return Collections.unmodifiableMap( map );
}
}

View File

@ -25,6 +25,7 @@ import org.geolatte.geom.jts.JTS;
*/
public class GeolatteGeometryJavaTypeDescriptor extends AbstractJavaTypeDescriptor<Geometry> {
final private Wkt.Dialect wktDialect;
/**
* an instance of this descriptor
*/
@ -34,17 +35,24 @@ public class GeolatteGeometryJavaTypeDescriptor extends AbstractJavaTypeDescript
* Initialize a type descriptor for the geolatte-geom {@code Geometry} type.
*/
public GeolatteGeometryJavaTypeDescriptor() {
this( Wkt.Dialect.SFA_1_1_0 );
}
public GeolatteGeometryJavaTypeDescriptor(Wkt.Dialect wktDialect) {
super( Geometry.class );
this.wktDialect = Wkt.Dialect.SFA_1_1_0;
}
@Override
public String toString(Geometry value) {
return value.toString();
return Wkt.toWkt( value, wktDialect );
}
@Override
public Geometry fromString(CharSequence string) {
return Wkt.fromWkt( string.toString() );
return Wkt.fromWkt( string.toString(), wktDialect );
}
@Override

View File

@ -0,0 +1,51 @@
/*
* 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;
import org.hibernate.dialect.Dialect;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkt;
import org.geolatte.geom.jts.JTS;
public class GeometryLiteralFormatter<T> implements JdbcLiteralFormatter<T> {
private final JavaType<T> javaType;
private final Wkt.Dialect wktDialect;
private final String geomFromTextName;
public GeometryLiteralFormatter(JavaType<T> javaType, Wkt.Dialect wktDialect, String geomFromTextName) {
this.javaType = javaType;
this.wktDialect = wktDialect;
this.geomFromTextName = geomFromTextName;
}
@Override
public void appendJdbcLiteral(
SqlAppender appender, T value, Dialect dialect, WrapperOptions wrapperOptions) {
appender.appendSql( geomFromTextName );
appender.appendSql( "('" );
if ( javaType instanceof GeolatteGeometryJavaTypeDescriptor ) {
appender.appendSql( Wkt.toWkt( (Geometry<?>) value, wktDialect ) );
}
else {
appender.appendSql( Wkt.toWkt( jts2Gl( value ), wktDialect ) );
}
appender.appendSql( "')" );
}
private <T> Geometry<?> jts2Gl(T value) {
return JTS.from( (org.locationtech.jts.geom.Geometry) value );
}
}

View File

@ -13,10 +13,12 @@ import java.util.function.Function;
import org.hibernate.dialect.CockroachDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.dialect.cockroachdb.CockroachDbContributor;
import org.hibernate.spatial.dialect.mariadb.MariaDBDialectContributor;
import org.hibernate.spatial.dialect.postgis.PostgisDialectContributor;
class ContributorResolver {
@ -29,6 +31,7 @@ class ContributorResolver {
//TypeContributorImplementor
CONTRIBUTOR_MAP.put( PostgreSQLDialect.class, PostgisDialectContributor::new );
CONTRIBUTOR_MAP.put( CockroachDialect.class, CockroachDbContributor::new );
CONTRIBUTOR_MAP.put( MariaDBDialect.class, MariaDBDialectContributor::new );
}
private ContributorResolver() {

View File

@ -19,6 +19,8 @@ import org.hibernate.spatial.contributor.ContributorImplementor;
import org.hibernate.spatial.dialect.postgis.PGGeometryType;
import org.hibernate.spatial.dialect.postgis.PostgisSqmFunctionDescriptors;
import org.geolatte.geom.codec.Wkt;
public class CockroachDbContributor implements ContributorImplementor {
private final ServiceRegistry serviceRegistry;

View File

@ -10,6 +10,7 @@ package org.hibernate.spatial.dialect.mariadb;
import org.hibernate.dialect.MariaDB103Dialect;
import org.hibernate.spatial.SpatialDialect;
@Deprecated
public class MariaDB103SpatialDialect extends MariaDB103Dialect implements SpatialDialect {
}

View File

@ -1,179 +0,0 @@
/*
* 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.mariadb;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
import org.hibernate.type.StandardBasicTypes;
class MariaDB103SpatialFunctions extends SpatialFunctionsRegistry {
public MariaDB103SpatialFunctions() {
functionMap.put(
"dimension", new StandardSQLFunction(
"ST_Dimension",
StandardBasicTypes.INTEGER
)
);
functionMap.put(
"geometrytype", new StandardSQLFunction(
"ST_GeometryType", StandardBasicTypes.STRING
)
);
functionMap.put(
"srid", new StandardSQLFunction(
"ST_SRID",
StandardBasicTypes.INTEGER
)
);
functionMap.put(
"envelope", new StandardSQLFunction(
"ST_Envelope"
)
);
functionMap.put(
"astext", new StandardSQLFunction(
"ST_Astext",
StandardBasicTypes.STRING
)
);
functionMap.put(
"asbinary", new StandardSQLFunction(
"ST_Asbinary",
StandardBasicTypes.BINARY
)
);
functionMap.put(
"isempty", new StandardSQLFunction(
"ST_IsEmpty",
StandardBasicTypes.BOOLEAN
)
);
functionMap.put(
"issimple", new StandardSQLFunction(
"ST_IsSimple",
StandardBasicTypes.BOOLEAN
)
);
functionMap.put(
"boundary", new StandardSQLFunction(
"ST_Boundary"
)
);
// Register functions for spatial relation constructs
functionMap.put(
"overlaps", new StandardSQLFunction(
"ST_Overlaps",
StandardBasicTypes.BOOLEAN
)
);
functionMap.put(
"intersects", new StandardSQLFunction(
"ST_Intersects",
StandardBasicTypes.BOOLEAN
)
);
functionMap.put(
"equals", new StandardSQLFunction(
"ST_Equals",
StandardBasicTypes.BOOLEAN
)
);
functionMap.put(
"contains", new StandardSQLFunction(
"ST_Contains",
StandardBasicTypes.BOOLEAN
)
);
functionMap.put(
"crosses", new StandardSQLFunction(
"ST_Crosses",
StandardBasicTypes.BOOLEAN
)
);
functionMap.put(
"disjoint", new StandardSQLFunction(
"ST_Disjoint",
StandardBasicTypes.BOOLEAN
)
);
functionMap.put(
"touches", new StandardSQLFunction(
"ST_Touches",
StandardBasicTypes.BOOLEAN
)
);
functionMap.put(
"within", new StandardSQLFunction(
"ST_Within",
StandardBasicTypes.BOOLEAN
)
);
functionMap.put(
"relate", new StandardSQLFunction(
"ST_Relate",
StandardBasicTypes.BOOLEAN
)
);
// register the spatial analysis functions
functionMap.put(
"distance", new StandardSQLFunction(
"ST_Distance",
StandardBasicTypes.DOUBLE
)
);
functionMap.put(
"buffer", new StandardSQLFunction(
"ST_Buffer"
)
);
functionMap.put(
"convexhull", new StandardSQLFunction(
"ST_ConvexHull"
)
);
functionMap.put(
"difference", new StandardSQLFunction(
"ST_Difference"
)
);
functionMap.put(
"intersection", new StandardSQLFunction(
"ST_Intersection"
)
);
functionMap.put(
"symdifference", new StandardSQLFunction(
"ST_SymDifference"
)
);
functionMap.put(
"geomunion", new StandardSQLFunction(
"ST_Union"
)
);
functionMap.put(
SpatialFunction.filter.name(), new StandardSQLFunction(
"MBRIntersects",
StandardBasicTypes.BOOLEAN
)
);
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.mariadb;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.KeyedSqmFunctionDescriptors;
import org.hibernate.spatial.contributor.ContributorImplementor;
public class MariaDBDialectContributor implements ContributorImplementor {
private final ServiceRegistry serviceRegistry;
public MariaDBDialectContributor(ServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry;
}
public void contributeTypes(TypeContributions typeContributions) {
HSMessageLogger.LOGGER.typeContributions( this.getClass().getCanonicalName() );
typeContributions.contributeType( new GeolatteGeometryType( MariaDBGeometryType.INSTANCE ) );
typeContributions.contributeType( new JTSGeometryType( MariaDBGeometryType.INSTANCE ) );
}
@Override
public void contributeFunctions(FunctionContributions functionContributions) {
HSMessageLogger.LOGGER.functionContributions( this.getClass().getCanonicalName() );
final KeyedSqmFunctionDescriptors mariaDbFunctions = new MariaDBSqmFunctionDescriptors( functionContributions );
final SqmFunctionRegistry functionRegistry = functionContributions.getFunctionRegistry();
mariaDbFunctions.asMap().forEach( (key, desc) -> {
functionRegistry.register( key.getName(), desc );
key.getAltName().ifPresent( altName -> functionRegistry.registerAlternateKey( altName, key.getName() ) );
} );
}
@Override
public ServiceRegistry getServiceRegistry() {
return this.serviceRegistry;
}
}

View File

@ -13,6 +13,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.spatial.GeometryLiteralFormatter;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
@ -20,6 +21,7 @@ import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.BasicBinder;
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.geolatte.geom.ByteBuffer;
@ -28,6 +30,7 @@ import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkb;
import org.geolatte.geom.codec.WkbDecoder;
import org.geolatte.geom.codec.WkbEncoder;
import org.geolatte.geom.codec.Wkt;
public class MariaDBGeometryType implements JdbcType {
@ -45,6 +48,11 @@ public class MariaDBGeometryType implements JdbcType {
return SqlTypes.GEOMETRY;
}
@Override
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaTypeDescriptor) {
return new GeometryLiteralFormatter<T>( javaTypeDescriptor, Wkt.Dialect.SFA_1_1_0, "ST_GeomFromText" );
}
@Override
public <X> ValueBinder<X> getBinder(JavaType<X> javaTypeDescriptor) {
@ -94,7 +102,7 @@ public class MariaDBGeometryType implements JdbcType {
};
}
private Geometry<?> toGeometry(byte[] bytes) {
public Geometry<?> toGeometry(byte[] bytes) {
if ( bytes == null ) {
return null;
}

View File

@ -1,100 +0,0 @@
/*
* 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.mariadb;
import java.util.Locale;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.JTSGeometryJavaTypeDescriptor;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.SpatialRelation;
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
public interface MariaDBSpatialDialectTrait extends SpatialDialect {
default void delegateContributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
typeContributions.contributeType( new GeolatteGeometryType( MariaDBGeometryType.INSTANCE ) );
typeContributions.contributeType( new JTSGeometryType( MariaDBGeometryType.INSTANCE ) );
typeContributions.contributeJavaTypeDescriptor( GeolatteGeometryJavaTypeDescriptor.INSTANCE );
typeContributions.contributeJavaTypeDescriptor( JTSGeometryJavaTypeDescriptor.INSTANCE );
}
SpatialFunctionsRegistry spatialFunctions();
default String getSpatialRelateSQL(String columnName, int spatialRelation) {
switch ( spatialRelation ) {
case SpatialRelation.WITHIN:
return " ST_within(" + columnName + ",?)";
case SpatialRelation.CONTAINS:
return " ST_contains(" + columnName + ", ?)";
case SpatialRelation.CROSSES:
return " ST_crosses(" + columnName + ", ?)";
case SpatialRelation.OVERLAPS:
return " ST_overlaps(" + columnName + ", ?)";
case SpatialRelation.DISJOINT:
return " ST_disjoint(" + columnName + ", ?)";
case SpatialRelation.INTERSECTS:
return " ST_intersects(" + columnName
+ ", ?)";
case SpatialRelation.TOUCHES:
return " ST_touches(" + columnName + ", ?)";
case SpatialRelation.EQUALS:
return " ST_equals(" + columnName + ", ?)";
default:
throw new IllegalArgumentException(
"Spatial relation is not known by this dialect"
);
}
}
default String getSpatialFilterExpression(String columnName) {
return String.format( Locale.ENGLISH, "MBRIntersects(%s,?)", columnName
);
}
default String getSpatialAggregateSQL(String columnName, int aggregation) {
throw new UnsupportedOperationException( "MariaDB has no spatial aggregate functions." );
}
default String getDWithinSQL(String columnName) {
throw new UnsupportedOperationException( "MariaDB doesn't support the DWithin function." );
}
default String getHavingSridSQL(String columnName) {
return " (ST_SRID(" + columnName + ") = ?) ";
}
default String getIsEmptySQL(String columnName, boolean isEmpty) {
final String emptyExpr = " ST_IsEmpty(" + columnName + ") ";
return isEmpty ? emptyExpr : "( NOT " + emptyExpr + ")";
}
default boolean supportsFiltering() {
return true;
}
default boolean supports(SpatialFunction function) {
return spatialFunctions().get( function.toString() ) != null;
}
}

View File

@ -0,0 +1,28 @@
/*
* 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.mariadb;
import java.util.Arrays;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.spatial.BaseSqmFunctionDescriptors;
import org.hibernate.spatial.CommonSpatialFunction;
public class MariaDBSqmFunctionDescriptors extends BaseSqmFunctionDescriptors {
public MariaDBSqmFunctionDescriptors(FunctionContributions functionContributions) {
super( functionContributions );
}
@Override
public CommonSpatialFunction[] filter(CommonSpatialFunction[] functions) {
return Arrays.stream( functions )
//todo -- investigate in more detail why st_relate fails
.filter(f -> f != CommonSpatialFunction.ST_RELATE )
.toArray( CommonSpatialFunction[]::new);
}
}

View File

@ -0,0 +1,11 @@
/*
* 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.mysql;
public class MySQLDialectContributor {
}

View File

@ -27,6 +27,7 @@ import org.hibernate.spatial.dialect.WithCustomJPAFilter;
import org.jboss.logging.Logger;
import org.geolatte.geom.codec.Wkt;
import org.geolatte.geom.codec.db.oracle.ConnectionFinder;
import org.geolatte.geom.codec.db.oracle.OracleJDBCTypeFactory;

View File

@ -14,6 +14,7 @@ import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
import org.hibernate.spatial.GeometryLiteralFormatter;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
@ -52,22 +53,7 @@ public class PGGeometryType implements JdbcType {
@Override
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaTypeDescriptor) {
if ( javaTypeDescriptor instanceof GeolatteGeometryJavaTypeDescriptor ) {
return (appender, value, dialect, wrapperOptions) -> {
appender.appendSql( "ST_GeomFromEWKT('" );
appender.appendSql( value.toString() );
appender.appendSql( "')" );
};
}
return (appender, value, dialect, wrapperOptions) -> {
appender.appendSql( "ST_GeomFromEWKT('" );
appender.appendSql( jts2Gl( value ).toString() );
appender.appendSql( "')" );
};
}
private <T> Geometry<?> jts2Gl(T value) {
return JTS.from( (org.locationtech.jts.geom.Geometry) value );
return new GeometryLiteralFormatter<T>( javaTypeDescriptor, Wkt.Dialect.POSTGIS_EWKT_1, "ST_GeomFromEwkt" );
}
private PGGeometryType(Wkb.Dialect dialect) {

View File

@ -16,6 +16,8 @@ import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.contributor.ContributorImplementor;
import org.geolatte.geom.codec.Wkt;
public class PostgisDialectContributor implements ContributorImplementor {
private final ServiceRegistry serviceRegistryegistry;

View File

@ -7,53 +7,22 @@
package org.hibernate.spatial.dialect.postgis;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Arrays;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.query.sqm.function.NamedSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.spatial.BaseSqmFunctionDescriptors;
import org.hibernate.spatial.CommonSpatialFunction;
import org.hibernate.spatial.FunctionKey;
import org.hibernate.spatial.KeyedSqmFunctionDescriptors;
import org.hibernate.type.BasicTypeRegistry;
import static org.hibernate.spatial.CommonSpatialFunction.values;
public class PostgisSqmFunctionDescriptors implements KeyedSqmFunctionDescriptors {
private final Map<FunctionKey, SqmFunctionDescriptor> map = new HashMap<>();
public class PostgisSqmFunctionDescriptors extends BaseSqmFunctionDescriptors {
public PostgisSqmFunctionDescriptors(FunctionContributions functionContributions) {
final BasicTypeRegistry basicTypeRegistry = functionContributions.getTypeConfiguration().getBasicTypeRegistry();
for ( CommonSpatialFunction func : values() ) {
final FunctionReturnTypeResolver returnTypeResolver;
if ( func.getReturnType() == null ) {
returnTypeResolver = null;
}
else {
returnTypeResolver = StandardFunctionReturnTypeResolvers.invariant(
basicTypeRegistry.resolve( func.getReturnType() )
);
}
map.put(
func.getKey(),
new NamedSqmFunctionDescriptor(
func.getKey().getName(),
true,
StandardArgumentsValidators.exactly( func.getNumArgs() ),
returnTypeResolver
)
);
}
super( functionContributions );
}
public Map<FunctionKey, SqmFunctionDescriptor> asMap() {
return Collections.unmodifiableMap( map );
}
}

View File

@ -10,7 +10,6 @@ import java.io.Serializable;
import java.util.Map;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
@ -41,7 +40,6 @@ class SqlServerSupport implements SpatialDialect, Serializable {
}
public String getSpatialRelateSQL(String columnName, int spatialRelation) {
final String stfunction;
switch ( spatialRelation ) {
@ -78,38 +76,38 @@ class SqlServerSupport implements SpatialDialect, Serializable {
return columnName + "." + stfunction + "(?) = 1";
}
public String getSpatialFilterExpression(String columnName) {
return columnName + ".Filter(?) = 1";
}
public String getSpatialAggregateSQL(String columnName, int aggregation) {
throw new UnsupportedOperationException( "No spatial aggregate SQL functions." );
}
public String getDWithinSQL(String columnName) {
throw new UnsupportedOperationException( "SQL Server has no DWithin function." );
}
public String getHavingSridSQL(String columnName) {
return columnName + ".STSrid = (?)";
}
public String getIsEmptySQL(String columnName, boolean isEmpty) {
final String base = "(" + columnName + ".STIsEmpty() ";
return isEmpty ? base + " = 1 )" : base + " = 0 )";
}
public boolean supportsFiltering() {
return true;
}
public boolean supports(SpatialFunction function) {
return ( functions.get( function.toString() ) != null );
}

View File

@ -95,7 +95,7 @@ public class FunctionTestTemplate {
query.addScalar( "result", spatialFunction.getReturnType() );
}
if ( testGeometry != null ) {
query.setParameter( "filter", Wkt.toWkt( testGeometry ) );
query.setParameter( "filter", Wkt.toWkt( testGeometry, Wkt.Dialect.SFA_1_1_0 ) );
}
return query;
@ -129,7 +129,7 @@ public class FunctionTestTemplate {
private Object mapRow(Object object) {
Data data = rowObjectMapper.apply( object );
if ( this.spatialFunction.returnsGeometry() ) {
data.datum = this.model.from.apply( codec.toGeometry( data.datum ) );
data.datum = data.datum != null ? this.model.from.apply( codec.toGeometry( data.datum ) ) : null;
return data;
}
return data;

View File

@ -9,6 +9,7 @@ package org.hibernate.spatial.testing;
import org.hibernate.dialect.CockroachDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.testing.orm.junit.DialectFeatureCheck;
@ -24,6 +25,7 @@ public class IsSupportedBySpatial implements DialectFeatureCheck {
@Override
public boolean apply(Dialect dialect) {
return dialect instanceof PostgreSQLDialect
|| dialect instanceof CockroachDialect;
|| dialect instanceof CockroachDialect
|| dialect instanceof MariaDBDialect;
}
}

View File

@ -49,7 +49,7 @@ public class TestSupportFactories {
return PostgisTestSupport.class;
}
if ( ( dialect instanceof SpatialDialect ) && MariaDBDialect.class.isAssignableFrom( dialect.getClass() ) ) {
if ( MariaDBDialect.class.isAssignableFrom( dialect.getClass() ) ) {
return MariaDBTestSupport.class;
}

View File

@ -19,42 +19,42 @@ public class PredicateRegexes {
// Note that we alias the function invocation so that
// we can map the return value to the required type
public PredicateRegexes() {
public PredicateRegexes(String geomFromTextFunction) {
add(
"overlaps",
"select .* from .* where st_overlaps\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=true.*",
"select .* from .* where st_overlaps\\(.*geom\\s*,.*" + geomFromTextFunction + "\\(.*\\)\\s*=.*",
"select .* from .* where st_overlaps\\(.*geom\\s*,.s*?\\)\\s*=\\s*?.*"
);
add(
"crosses",
"select .* from .* where st_crosses\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=true.*",
"select .* from .* where st_crosses\\(.*geom\\s*,.*" + geomFromTextFunction + "\\(.*\\)\\s*=.*",
"select .* from .* where st_crosses\\(.*geom\\s*,.s*?\\)\\s*=\\s*?.*"
);
add(
"contains",
"select .* from .* where st_contains\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=true.*",
"select .* from .* where st_contains\\(.*geom\\s*,.*" + geomFromTextFunction + "\\(.*\\)\\s*=.*",
"select .* from .* where st_contains\\(.*geom\\s*,.s*?\\)\\s*=\\s*?.*"
);
add(
"disjoint",
"select .* from .* where st_disjoint\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=true.*",
"select .* from .* where st_disjoint\\(.*geom\\s*,.*" + geomFromTextFunction + "\\(.*\\)\\s*=.*",
"select .* from .* where st_disjoint\\(.*geom\\s*,.s*?\\)\\s*=\\s*?.*"
);
add(
"touches",
"select .* from .* where st_touches\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=true.*",
"select .* from .* where st_touches\\(.*geom\\s*,.*" + geomFromTextFunction + "\\(.*\\)\\s*=.*",
"select .* from .* where st_touches\\(.*geom\\s*,.s*?\\)\\s*=\\s*?.*"
);
add(
"within",
"select .* from .* where st_within\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=true.*",
"select .* from .* where st_within\\(.*geom\\s*,.*" + geomFromTextFunction + "\\(.*\\)\\s*=.*",
"select .* from .* where st_within\\(.*geom\\s*,.s*?\\)\\s*=\\s*?.*"
);
add(
"eq",
"select .* from .* where st_equals\\(.*geom\\s*,.*st_geomfromewkt\\(.*\\)\\s*=true.*",
"select .* from .* where st_equals\\(.*geom\\s*,.*" + geomFromTextFunction + "\\(.*\\)\\s*=.*",
"select .* from .* where st_equals\\(.*geom\\s*,.s*?\\)\\s*=\\s*?.*"
);

View File

@ -27,7 +27,7 @@ public class CockroachDBTestSupport extends TestSupport {
@Override
public PredicateRegexes predicateRegexes() {
return new CrPredicateRegexes();
return new PredicateRegexes("st_geomfromewkt");
}
@Override
@ -54,6 +54,4 @@ public class CockroachDBTestSupport extends TestSupport {
};
}
}
class CrPredicateRegexes extends PredicateRegexes{ }
}

View File

@ -7,9 +7,21 @@
package org.hibernate.spatial.testing.dialects.mariadb;
import java.util.Map;
import org.hibernate.spatial.CommonSpatialFunction;
import org.hibernate.spatial.GeomCodec;
import org.hibernate.spatial.dialect.mariadb.MariaDBGeometryType;
import org.hibernate.spatial.dialect.postgis.PGGeometryType;
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.datareader.TestData;
import org.hibernate.spatial.testing.datareader.TestSupport;
import org.hibernate.spatial.testing.dialects.NativeSQLTemplates;
import org.hibernate.spatial.testing.dialects.PredicateRegexes;
import org.hibernate.spatial.testing.dialects.mysql.MySqlNativeSqlTemplates;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkt;
public class MariaDBTestSupport extends TestSupport {
@ -18,4 +30,33 @@ public class MariaDBTestSupport extends TestSupport {
return TestData.fromFile( "mariadb/test-mariadb-functions-data-set.xml" );
}
@Override
public NativeSQLTemplates templates() {
return new MySqlNativeSqlTemplates();
}
@Override
public Map<CommonSpatialFunction, String> hqlOverrides() {
return super.hqlOverrides();
}
@Override
public PredicateRegexes predicateRegexes() {
return new PredicateRegexes("st_geomfromtext");
}
@Override
public GeomCodec codec() {
return new GeomCodec() {
@Override
public Geometry<?> toGeometry(Object in) {
return MariaDBGeometryType.INSTANCE.toGeometry( (byte[])in );
}
@Override
public Object fromGeometry(Geometry<?> in) {
return Wkt.toWkt( in, Wkt.Dialect.MYSQL_WKT );
}
};
}
}

View File

@ -0,0 +1,14 @@
/*
* 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.dialects.mysql;
import org.hibernate.spatial.testing.dialects.NativeSQLTemplates;
public class MySqlNativeSqlTemplates extends NativeSQLTemplates {
}

View File

@ -10,7 +10,4 @@ package org.hibernate.spatial.testing.dialects.postgis;
import org.hibernate.spatial.testing.dialects.NativeSQLTemplates;
public class PostgisNativeSQLTemplates extends NativeSQLTemplates {
public PostgisNativeSQLTemplates() {
super();
}
}

View File

@ -36,7 +36,7 @@ public class PostgisTestSupport extends TestSupport {
}
@Override
public PredicateRegexes predicateRegexes(){ return new PostgisPredicateRegexes();}
public PredicateRegexes predicateRegexes(){ return new PredicateRegexes("st_geomfromewkt");}
//TODO put this in its own class (analogous to NativeSQLTemplates)
@Override
@ -71,5 +71,3 @@ public class PostgisTestSupport extends TestSupport {
}
}
class PostgisPredicateRegexes extends PredicateRegexes { }

View File

@ -34,6 +34,13 @@ hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFa
#hibernate.connection.username hibernate_orm_test
#hibernate.connection.password hibernate_orm_test
#
#hibernate.dialect org.hibernate.dialect.MariaDBDialect
#hibernate.connection.driver_class org.mariadb.jdbc.Driver
#hibernate.connection.url jdbc:mariadb://localhost/hibernate_orm_test
#hibernate.connection.username hibernate_orm_test
#hibernate.connection.password hibernate_orm_test
## GeoDb (H2 spatial extension)
##
#hibernate.dialect org.hibernate.spatial.dialect.h2geodb.GeoDBDialect

View File

@ -15,48 +15,48 @@ Tests for MariaDB spatial
<Element>
<id>1</id>
<type>POINT</type>
<wkt>SRID=31370;POINT(10 5)</wkt>
<wkt>SRID=4326;POINT(10 5)</wkt>
</Element>
<Element>
<id>2</id>
<type>POINT</type>
<wkt>SRID=31370;POINT(52.25 2.53)</wkt>
<wkt>SRID=4326;POINT(52.25 2.53)</wkt>
</Element>
<Element>
<id>3</id>
<type>POINT</type>
<wkt>SRID=31370;POINT(51 12)</wkt>
<wkt>SRID=4326;POINT(51 12)</wkt>
</Element>
<Element>
<id>4</id>
<type>POINT</type>
<wkt>SRID=31370;POINT(10.0 2.0)</wkt>
<wkt>SRID=4326;POINT(10.0 2.0)</wkt>
</Element>
<Element>
<id>5</id>
<type>LINESTRING</type>
<wkt>SRID=31370;LINESTRING(10.0 5.0, 20.0 15.0)</wkt>
<wkt>SRID=4326;LINESTRING(10.0 5.0, 20.0 15.0)</wkt>
</Element>
<Element>
<id>6</id>
<type>LINESTRING</type>
<wkt>SRID=31370;LINESTRING(10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0)</wkt>
<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=31370;MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0))</wkt>
<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=31370;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
<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>
@ -65,28 +65,28 @@ Tests for MariaDB spatial
<Element>
<id>16</id>
<type>POLYGON</type>
<wkt>SRID=31370;POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) )</wkt>
<wkt>SRID=4326;POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) )</wkt>
</Element>
<Element>
<id>18</id>
<type>POLYGON</type>
<wkt>SRID=31370;POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 5, 5 5,5 2, 2 2))</wkt>
<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=31370;POLYGON( (50 50, 50 70, 70 70, 70 50, 50 50) )</wkt>
<wkt>SRID=4326;POLYGON( (50 50, 50 70, 70 70, 70 50, 50 50) )</wkt>
</Element>
<Element>
<id>20</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=31370;MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((55 50, 60 70, 70 78, 55 50)) )</wkt>
<wkt>SRID=4326;MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((55 50, 60 70, 70 78, 55 50)) )</wkt>
</Element>
<Element>
<id>22</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=31370;MULTIPOLYGON(( (0 0, 0 50, 50 50, 50 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10) ),((15 10, 12
<wkt>SRID=4326;MULTIPOLYGON(( (0 0, 0 50, 50 50, 50 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10) ),((15 10, 12
14, 13
14, 15 10)) )
</wkt>
@ -96,28 +96,28 @@ Tests for MariaDB spatial
<Element>
<id>25</id>
<type>MULTIPOINT</type>
<wkt>SRID=31370;MULTIPOINT(21 2, 25 5, 30 3)</wkt>
<wkt>SRID=4326;MULTIPOINT(21 2, 25 5, 30 3)</wkt>
</Element>
<Element>
<id>26</id>
<type>MULTIPOINT</type>
<wkt>SRID=31370;MULTIPOINT(21 2)</wkt>
<wkt>SRID=4326;MULTIPOINT(21 2)</wkt>
</Element>
<Element>
<id>30</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=31370;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3))</wkt>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>31</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=31370;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0)))</wkt>
<wkt>SRID=4326;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=31370;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0),(1 1, 2 1,
<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,
1 1)))
</wkt>
@ -125,7 +125,7 @@ Tests for MariaDB spatial
<Element>
<id>33</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=31370;GEOMETRYCOLLECTION( MULTIPOINT(21 2, 25 5, 30 3), MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)),
<wkt>SRID=4326;GEOMETRYCOLLECTION( MULTIPOINT(21 2, 25 5, 30 3), MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)),
((15 10,
12 14, 13 14, 15 10)) ), MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0)))
</wkt>

View File

@ -16,48 +16,48 @@ In MySQL these are stored as null objects.
<Element>
<id>1</id>
<type>POINT</type>
<wkt>SRID=31370;POINT(10 5)</wkt>
<wkt>SRID=4326;POINT(10 5)</wkt>
</Element>
<Element>
<id>2</id>
<type>POINT</type>
<wkt>SRID=31370;POINT(52.25 2.53)</wkt>
<wkt>SRID=4326;POINT(52.25 2.53)</wkt>
</Element>
<Element>
<id>3</id>
<type>POINT</type>
<wkt>SRID=31370;POINT(51 12)</wkt>
<wkt>SRID=4326;POINT(51 12)</wkt>
</Element>
<Element>
<id>4</id>
<type>POINT</type>
<wkt>SRID=31370;POINT(10.0 2.0)</wkt>
<wkt>SRID=4326;POINT(10.0 2.0)</wkt>
</Element>
<Element>
<id>5</id>
<type>LINESTRING</type>
<wkt>SRID=31370;LINESTRING(10.0 5.0, 20.0 15.0)</wkt>
<wkt>SRID=4326;LINESTRING(10.0 5.0, 20.0 15.0)</wkt>
</Element>
<Element>
<id>6</id>
<type>LINESTRING</type>
<wkt>SRID=31370;LINESTRING(10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0)</wkt>
<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=31370;MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0))</wkt>
<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=31370;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
<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>
@ -66,28 +66,28 @@ In MySQL these are stored as null objects.
<Element>
<id>16</id>
<type>POLYGON</type>
<wkt>SRID=31370;POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) )</wkt>
<wkt>SRID=4326;POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) )</wkt>
</Element>
<Element>
<id>18</id>
<type>POLYGON</type>
<wkt>SRID=31370;POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 5, 5 5,5 2, 2 2))</wkt>
<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=31370;POLYGON( (50 50, 50 70, 70 70, 70 50, 50 50) )</wkt>
<wkt>SRID=4326;POLYGON( (50 50, 50 70, 70 70, 70 50, 50 50) )</wkt>
</Element>
<Element>
<id>20</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=31370;MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((55 50, 60 70, 70 78, 55 50)) )</wkt>
<wkt>SRID=4326;MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((55 50, 60 70, 70 78, 55 50)) )</wkt>
</Element>
<Element>
<id>22</id>
<type>MULTIPOLYGON</type>
<wkt>SRID=31370;MULTIPOLYGON(( (0 0, 0 50, 50 50, 50 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10) ),((15 10, 12
<wkt>SRID=4326;MULTIPOLYGON(( (0 0, 0 50, 50 50, 50 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10) ),((15 10, 12
14, 13
14, 15 10)) )
</wkt>
@ -97,28 +97,28 @@ In MySQL these are stored as null objects.
<Element>
<id>25</id>
<type>MULTIPOINT</type>
<wkt>SRID=31370;MULTIPOINT(21 2, 25 5, 30 3)</wkt>
<wkt>SRID=4326;MULTIPOINT(21 2, 25 5, 30 3)</wkt>
</Element>
<Element>
<id>26</id>
<type>MULTIPOINT</type>
<wkt>SRID=31370;MULTIPOINT(21 2)</wkt>
<wkt>SRID=4326;MULTIPOINT(21 2)</wkt>
</Element>
<Element>
<id>30</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=31370;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3))</wkt>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>31</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=31370;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0)))</wkt>
<wkt>SRID=4326;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=31370;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0),(1 1, 2 1,
<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,
1 1)))
</wkt>
@ -126,7 +126,7 @@ In MySQL these are stored as null objects.
<Element>
<id>33</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=31370;GEOMETRYCOLLECTION( MULTIPOINT(21 2, 25 5, 30 3), MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)),
<wkt>SRID=4326;GEOMETRYCOLLECTION( MULTIPOINT(21 2, 25 5, 30 3), MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)),
((15 10,
12 14, 13 14, 15 10)) ), MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0)))
</wkt>