HHH-14805 Upgrade SqlServer Spatial to H6

This commit is contained in:
Karel Maesen 2022-01-22 14:36:24 +01:00
parent a332d9191e
commit 4b7b6135fe
21 changed files with 462 additions and 494 deletions

View File

@ -229,14 +229,6 @@ ext {
'jdbc.url' : 'jdbc:sqlserver://' + dbHost + ';databaseName=hibernate_orm_test',
'connection.init_sql' : ''
],
mssql_spatial_ci : [
'db.dialect' : 'org.hibernate.spatial.dialect.sqlserver.SqlServer2012SpatialDialect',
'jdbc.driver': 'com.microsoft.sqlserver.jdbc.SQLServerDriver',
'jdbc.user' : 'sa',
'jdbc.pass' : 'Hibernate_orm_test',
'jdbc.url' : 'jdbc:sqlserver://' + dbHost + ';databaseName=hibernate_orm_test',
'connection.init_sql' : ''
],
informix : [
'db.dialect' : 'org.hibernate.dialect.InformixDialect',
'jdbc.driver': 'com.informix.jdbc.IfxDriver',

View File

@ -49,7 +49,9 @@ tasks.test {
'mysql_docker',
'oracle_docker',
'oracle_ci',
'oracle_rds'
'oracle_rds',
'mssql',
'mssql_ci'
].contains( project.db )
}

View File

@ -29,6 +29,8 @@ import org.hibernate.type.BasicTypeRegistry;
public class BaseSqmFunctionDescriptors implements KeyedSqmFunctionDescriptors {
protected final Map<FunctionKey, SqmFunctionDescriptor> map = new HashMap<>();
//TODO -- refactor so that the function registration is done a separate function so that it can be
//overwritten by subclasses
public BaseSqmFunctionDescriptors(FunctionContributions functionContributions) {
final BasicTypeRegistry basicTypeRegistry = functionContributions.getTypeConfiguration().getBasicTypeRegistry();
for ( CommonSpatialFunction func : filter( CommonSpatialFunction.values() ) ) {

View File

@ -18,6 +18,7 @@ import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.dialect.cockroachdb.CockroachDbContributor;
@ -26,6 +27,7 @@ import org.hibernate.spatial.dialect.mariadb.MariaDBDialectContributor;
import org.hibernate.spatial.dialect.mysql.MySQLDialectContributor;
import org.hibernate.spatial.dialect.oracle.OracleDialectContributor;
import org.hibernate.spatial.dialect.postgis.PostgisDialectContributor;
import org.hibernate.spatial.dialect.sqlserver.SqlServerDialectContributor;
class ContributorResolver {
@ -40,6 +42,7 @@ class ContributorResolver {
CONTRIBUTOR_MAP.put( MySQLDialect.class, MySQLDialectContributor::new );
CONTRIBUTOR_MAP.put( H2Dialect.class, H2GisDialectContributor::new );
CONTRIBUTOR_MAP.put( OracleDialect.class, OracleDialectContributor::new );
CONTRIBUTOR_MAP.put( SQLServerDialect.class, SqlServerDialectContributor::new );
}
private ContributorResolver() {

View File

@ -15,7 +15,9 @@ import org.hibernate.spatial.SpatialDialect;
* The <code>SpatialDialect</code> for Microsoft SQL Server (2008).
*
* @author Karel Maesen, Martin Steinwender.
* @deprecated A SpatialDialect is no longer required. Use the standard Dialect for this database.
*/
@Deprecated
public class SqlServer2008SpatialDialect extends SQLServer2008Dialect implements SpatialDialect {
}

View File

@ -11,7 +11,9 @@ import org.hibernate.spatial.SpatialDialect;
/**
* Created by Karel Maesen, Geovise BVBA on 19/09/2018.
* @deprecated A SpatialDialect is no longer required. Use the standard Dialect for this database.
*/
@Deprecated
public class SqlServer2012SpatialDialect extends SQLServer2012Dialect implements SpatialDialect {
}

View File

@ -0,0 +1,45 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.dialect.sqlserver;
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.HSMessageLogger;
import org.hibernate.spatial.contributor.ContributorImplementor;
public class SqlServerDialectContributor implements ContributorImplementor {
private final ServiceRegistry serviceRegistry;
public SqlServerDialectContributor(ServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry;
}
@Override
public void contributeJdbcTypes(TypeContributions typeContributions) {
HSMessageLogger.LOGGER.typeContributions( this.getClass().getCanonicalName() );
typeContributions.contributeJdbcType( SqlServerGeometryType.INSTANCE );
}
@Override
public void contributeFunctions(FunctionContributions functionContributions) {
HSMessageLogger.LOGGER.functionContributions( this.getClass().getCanonicalName() );
final SqlServerSqmFunctionDescriptors functions = new SqlServerSqmFunctionDescriptors( functionContributions );
final SqmFunctionRegistry functionRegistry = functionContributions.getFunctionRegistry();
functions.asMap().forEach( (key, desc) -> {
functionRegistry.register( key.getName(), desc );
key.getAltName().ifPresent( altName -> functionRegistry.registerAlternateKey( altName, key.getName() ) );
} );
}
@Override
public ServiceRegistry getServiceRegistry() {
return serviceRegistry;
}
}

View File

@ -1,67 +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.sqlserver;
/**
* Created by Karel Maesen, Geovise BVBA on 19/09/2018.
*/
class SqlServerFunctions{
public SqlServerFunctions() {
//TODO -- re-implement. In 6.0 there is no longer a SQLFunctionTemplate class
// put( "dimension", new SQLFunctionTemplate( StandardBasicTypes.INTEGER, "?1.STDimension()" ) );
// put( "geometrytype", new SQLFunctionTemplate( StandardBasicTypes.STRING, "?1.STGeometryType()" ) );
// put( "srid", new SQLFunctionTemplate( StandardBasicTypes.INTEGER, "?1.STSrid" ) );
// put( "envelope", new SqlServerMethod( "STEnvelope" ) );
// put( "astext", new SQLFunctionTemplate( StandardBasicTypes.STRING, "?1.STAsText()" ) );
// put( "asbinary", new SQLFunctionTemplate( StandardBasicTypes.BINARY, "?1.STAsBinary()" ) );
//
// put( "isempty", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STIsEmpty()" ) );
// put( "issimple", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STIsSimple()" ) );
// put( "boundary", new SqlServerMethod( "STBoundary" ) );
//
// // section 2.1.1.2
// // Register functions for spatial relation constructs
// put( "contains", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STContains(?2)" ) );
// put( "crosses", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STCrosses(?2)" ) );
// put( "disjoint", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STDisjoint(?2)" ) );
// put( "equals", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STEquals(?2)" ) );
// put( "intersects", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STIntersects(?2)" ) );
// put( "overlaps", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STOverlaps(?2)" ) );
// put( "touches", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STTouches(?2)" ) );
// put( "within", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STWithin(?2)" ) );
// put( "relate", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STRelate(?2,?3)" ) );
//
// // section 2.1.1.3
// // Register spatial analysis functions.
// put( "distance", new SQLFunctionTemplate( StandardBasicTypes.DOUBLE, "?1.STDistance(?2)" ) );
// put( "buffer", new SqlServerMethod( "STBuffer" ) );
// put( "convexhull", new SqlServerMethod( "STConvexHull" ) );
// put( "difference", new SqlServerMethod( "STDifference" ) );
// put( "intersection", new SqlServerMethod( "STIntersection" ) );
// put( "symdifference", new SqlServerMethod( "STSymDifference" ) );
// put( "geomunion", new SqlServerMethod( "STUnion" ) );
// // we rename OGC union to geomunion because union is a reserved SQL keyword.
// // (See also postgis documentation).
//
// // portable spatial aggregate functions
// // no aggregatefunctions implemented in sql-server2000
// //put("extent", new SQLFunctionTemplate(geomType, "?1.STExtent()"));
//
// // section 2.1.9.1 methods on surfaces
// put( "area", new SQLFunctionTemplate( StandardBasicTypes.DOUBLE, "?1.STArea()" ) );
// put( "centroid", new SqlServerMethod( "STCentroid" ) );
// put(
// "pointonsurface", new SqlServerMethod( "STPointOnSurface" )
// );
//
// // Register spatial filter function.
// put( SpatialFunction.filter.name(), new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.Filter(?2)" ) );
}
}

View File

@ -14,6 +14,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;
@ -21,9 +22,11 @@ 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.Geometry;
import org.geolatte.geom.codec.Wkt;
import org.geolatte.geom.codec.db.sqlserver.Decoders;
import org.geolatte.geom.codec.db.sqlserver.Encoders;
@ -33,12 +36,12 @@ import org.geolatte.geom.codec.db.sqlserver.Encoders;
* @author Karel Maesen, Geovise BVBA
* creation-date: 8/23/11
*/
public class SqlServer2008GeometryType implements JdbcType {
public class SqlServerGeometryType implements JdbcType {
/**
* An instance of the descrtiptor
*/
public static final SqlServer2008GeometryType INSTANCE = new SqlServer2008GeometryType();
public static final SqlServerGeometryType INSTANCE = new SqlServerGeometryType();
@Override
public int getJdbcTypeCode() {
@ -50,6 +53,11 @@ public class SqlServer2008GeometryType implements JdbcType {
return SqlTypes.GEOMETRY;
}
@Override
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
return new GeometryLiteralFormatter<>( javaType, Wkt.Dialect.SFA_1_2_1, "geometry::STGeomFromText" );
}
@Override
public <X> ValueBinder<X> getBinder(final JavaType<X> javaType) {
return new BasicBinder<X>( javaType, this ) {

View File

@ -1,44 +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.sqlserver;
import java.util.List;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.type.Type;
/**
* @author Karel Maesen, Geovise BVBA
* creation-date: 4/8/13
*/
class SqlServerMethod extends StandardSQLFunction {
public SqlServerMethod(String name) {
super( name );
}
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
final StringBuilder buf = new StringBuilder();
if ( arguments.size() < 1 ) {
buf.append( getName() ).append( "()" );
}
else {
buf.append( arguments.get( 0 ) ).append( "." )
.append( getName() ).append( "(" );
for ( int i = 1; i < arguments.size(); i++ ) {
buf.append( arguments.get( i ) );
if ( i < arguments.size() - 1 ) {
buf.append( "," );
}
}
buf.append( ")" );
}
return buf.toString();
}
}

View File

@ -0,0 +1,198 @@
/*
* 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.sqlserver;
import java.util.List;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.query.sqm.function.NamedSqmFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
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.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.BasicTypeReference;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.StandardBasicTypes;
public class SqlServerSqmFunctionDescriptors extends BaseSqmFunctionDescriptors {
private final BasicTypeRegistry typeRegistry;
public SqlServerSqmFunctionDescriptors(FunctionContributions functionContributions) {
super( functionContributions );
typeRegistry = functionContributions.getTypeConfiguration().getBasicTypeRegistry();
//TODO -- after refactoring base class this should be removed
map.clear();
map.put(
CommonSpatialFunction.ST_ASTEXT.getKey(),
new Method( "STAsText", exactly( 1 ), invariant( StandardBasicTypes.STRING ) )
);
map.put(
CommonSpatialFunction.ST_GEOMETRYTYPE.getKey(),
new Method( "STGeometryType", exactly( 1 ), invariant( StandardBasicTypes.STRING ) )
);
map.put(
CommonSpatialFunction.ST_DIMENSION.getKey(),
new Method( "STDimension", exactly( 1 ), invariant( StandardBasicTypes.INTEGER ) )
);
map.put( CommonSpatialFunction.ST_ENVELOPE.getKey(), new Method( "STEnvelope", exactly( 1 ), sameAsFirst() ) );
map.put(
CommonSpatialFunction.ST_SRID.getKey(),
new Property( "STSrid", exactly( 1 ), invariant( StandardBasicTypes.INTEGER ) )
);
map.put(
CommonSpatialFunction.ST_ASBINARY.getKey(),
new Method( "STAsBinary", exactly( 1 ), invariant( StandardBasicTypes.BINARY ) )
);
map.put(
CommonSpatialFunction.ST_ISEMPTY.getKey(),
new Method( "STIsEmpty", exactly( 1 ), invariant( StandardBasicTypes.BOOLEAN ) )
);
map.put(
CommonSpatialFunction.ST_ISSIMPLE.getKey(),
new Method( "STIsSimple", exactly( 1 ), invariant( StandardBasicTypes.BOOLEAN ) )
);
map.put( CommonSpatialFunction.ST_BOUNDARY.getKey(), new Method( "STBoundary", exactly( 1 ), sameAsFirst() ) );
map.put(
CommonSpatialFunction.ST_OVERLAPS.getKey(),
new Method( "STOverlaps", exactly( 2 ), invariant( StandardBasicTypes.BOOLEAN ) )
);
map.put(
CommonSpatialFunction.ST_INTERSECTS.getKey(),
new Method( "STIntersects", exactly( 2 ), invariant( StandardBasicTypes.BOOLEAN ) )
);
map.put(
CommonSpatialFunction.ST_CROSSES.getKey(),
new Method( "STCrosses", exactly( 2 ), invariant( StandardBasicTypes.BOOLEAN ) )
);
map.put(
CommonSpatialFunction.ST_CONTAINS.getKey(),
new Method( "STContains", exactly( 2 ), invariant( StandardBasicTypes.BOOLEAN ) )
);
map.put(
CommonSpatialFunction.ST_DISJOINT.getKey(),
new Method( "STDisjoint", exactly( 2 ), invariant( StandardBasicTypes.BOOLEAN ) )
);
map.put(
CommonSpatialFunction.ST_EQUALS.getKey(),
new Method( "STEquals", exactly( 2 ), invariant( StandardBasicTypes.BOOLEAN ) )
);
map.put(
CommonSpatialFunction.ST_TOUCHES.getKey(),
new Method( "STTouches", exactly( 2 ), invariant( StandardBasicTypes.BOOLEAN ) )
);
map.put(
CommonSpatialFunction.ST_WITHIN.getKey(),
new Method( "STWithin", exactly( 2 ), invariant( StandardBasicTypes.BOOLEAN ) )
);
map.put(
CommonSpatialFunction.ST_DISTANCE.getKey(),
new Method( "STDistance", exactly( 2 ), invariant( StandardBasicTypes.DOUBLE ) )
);
map.put( CommonSpatialFunction.ST_BUFFER.getKey(), new Method( "STBuffer", exactly( 2 ), sameAsFirst() ) );
map.put(
CommonSpatialFunction.ST_CONVEXHULL.getKey(),
new Method( "STConvexHull", exactly( 1 ), sameAsFirst() )
);
map.put(
CommonSpatialFunction.ST_DIFFERENCE.getKey(),
new Method( "STDifference", exactly( 2 ), sameAsFirst() )
);
map.put(
CommonSpatialFunction.ST_INTERSECTION.getKey(),
new Method( "STIntersection", exactly( 2 ), sameAsFirst() )
);
map.put(
CommonSpatialFunction.ST_SYMDIFFERENCE.getKey(),
new Method( "STSymDifference", exactly( 2 ), sameAsFirst() )
);
map.put( CommonSpatialFunction.ST_UNION.getKey(), new Method( "STUnion", exactly( 2 ), sameAsFirst() ) );
map.put(
CommonSpatialFunction.ST_RELATE.getKey(),
new Method( "STRelate", exactly( 3 ), invariant( StandardBasicTypes.BOOLEAN ) )
);
}
ArgumentsValidator exactly(int i) {
return StandardArgumentsValidators.exactly( i );
}
FunctionReturnTypeResolver invariant(BasicTypeReference<?> tpe) {
return StandardFunctionReturnTypeResolvers.invariant( typeRegistry.resolve( tpe ) );
}
FunctionReturnTypeResolver sameAsFirst() {
return StandardFunctionReturnTypeResolvers.useArgType( 1 );
}
}
class Property extends NamedSqmFunctionDescriptor {
Property(
String name, ArgumentsValidator argValidator, FunctionReturnTypeResolver returnTypeResolver) {
super( name, false, argValidator, returnTypeResolver );
}
@Override
public void render(
SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) {
final Expression arg1 = (Expression) sqlAstArguments.get( 0 );
walker.render( arg1, SqlAstNodeRenderingMode.DEFAULT );
sqlAppender.appendSql( "." );
sqlAppender.appendSql( getName() );
}
}
class Method extends NamedSqmFunctionDescriptor {
Method(
String name, ArgumentsValidator argValidator, FunctionReturnTypeResolver returnTypeResolver) {
super( name, true, argValidator, returnTypeResolver );
}
@Override
public void render(
SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) {
final Expression arg1 = (Expression) sqlAstArguments.get( 0 );
walker.render( arg1, SqlAstNodeRenderingMode.DEFAULT );
sqlAppender.appendSql( "." );
sqlAppender.appendSql( getName() );
sqlAppender.appendSql( '(' );
for ( int i = 1; i < sqlAstArguments.size(); i++ ) {
Expression argN = (Expression) sqlAstArguments.get( i );
walker.render( argN, SqlAstNodeRenderingMode.DEFAULT );
if ( i < sqlAstArguments.size() - 1 ) {
sqlAppender.appendSql( " ," );
}
}
sqlAppender.appendSql( ')' );
}
}

View File

@ -1,107 +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.sqlserver;
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.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.SpatialRelation;
/**
* Created by Karel Maesen, Geovise BVBA on 19/09/2018.
*/
class SqlServerSupport implements SpatialDialect, Serializable {
private SqlServerFunctions functions = new SqlServerFunctions();
//
// Iterable<? extends Map.Entry<String, SqmFunctionDescriptor>> functionsToRegister() {
// return functions;
// }
void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
}
public String getSpatialRelateSQL(String columnName, int spatialRelation) {
final String stfunction;
switch ( spatialRelation ) {
case SpatialRelation.WITHIN:
stfunction = "STWithin";
break;
case SpatialRelation.CONTAINS:
stfunction = "STContains";
break;
case SpatialRelation.CROSSES:
stfunction = "STCrosses";
break;
case SpatialRelation.OVERLAPS:
stfunction = "STOverlaps";
break;
case SpatialRelation.DISJOINT:
stfunction = "STDisjoint";
break;
case SpatialRelation.INTERSECTS:
stfunction = "STIntersects";
break;
case SpatialRelation.TOUCHES:
stfunction = "STTouches";
break;
case SpatialRelation.EQUALS:
stfunction = "STEquals";
break;
default:
throw new IllegalArgumentException(
"Spatial relation is not known by this dialect"
);
}
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 true;
}
}

View File

@ -10,7 +10,7 @@
<head></head>
<body>
<p>
This package contains the spatial extensions for the SqlServer2008 dialect.
This package contains the spatial extensions for the SqlServer dialect.
</p>
<p>Currently, only the Geometry type is supported.</p>
</body>

View File

@ -16,9 +16,12 @@ import org.hibernate.spatial.CommonSpatialFunction;
import org.hibernate.spatial.testing.IsSupportedBySpatial;
import org.hibernate.spatial.testing.SpatialTestBase;
import org.hibernate.spatial.testing.datareader.TestSupport;
import org.hibernate.spatial.testing.domain.GeomEntity;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.function.Executable;
@ -27,6 +30,7 @@ import static org.geolatte.geom.builder.DSL.g;
import static org.geolatte.geom.builder.DSL.polygon;
import static org.geolatte.geom.builder.DSL.ring;
@RequiresDialectFeature(feature = IsSupportedBySpatial.class)
@SessionFactory
public class TestGeometryConstructionWithParameter extends SpatialTestBase {
@ -59,6 +63,7 @@ public class TestGeometryConstructionWithParameter extends SpatialTestBase {
}
@TestFactory
@Disabled("Broken because of NULL argument return type")
public Stream<DynamicTest> testFunctions() {
return Arrays.stream( CommonSpatialFunction.values() )
.filter( f ->
@ -77,7 +82,7 @@ public class TestGeometryConstructionWithParameter extends SpatialTestBase {
return () -> {
scope.inSession( session -> {
String hql = templates.get( func );
session.createQuery( hql )
session.createQuery( hql , GeomEntity.class )
.setParameter( "poly", filterGeometry )
.getResultList();
//we just check that this parses for now.

View File

@ -14,6 +14,7 @@ import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.testing.orm.junit.DialectFeatureCheck;
@ -31,6 +32,7 @@ public class IsSupportedBySpatial implements DialectFeatureCheck {
|| dialect instanceof MySQLDialect
|| dialect instanceof MariaDBDialect
|| dialect instanceof OracleDialect
|| dialect instanceof SQLServerDialect
|| dialect instanceof H2Dialect;
}
}

View File

@ -14,6 +14,7 @@ import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.spatial.testing.datareader.TestSupport;
import org.hibernate.spatial.testing.dialects.cockroachdb.CockroachDBTestSupport;
import org.hibernate.spatial.testing.dialects.db2.DB2TestSupport;
@ -71,10 +72,7 @@ public class TestSupportFactories {
return OracleSDOTestSupport.class;
}
if ( "org.hibernate.spatial.dialect.sqlserver.SqlServer2008SpatialDialect".equals( canonicalName ) ) {
return SQLServerTestSupport.class;
}
if ( "org.hibernate.spatial.dialect.sqlserver.SqlServer2012SpatialDialect".equals( canonicalName ) ) {
if ( SQLServerDialect.class.isAssignableFrom( dialect.getClass() ) ) {
return SQLServerTestSupport.class;
}

View File

@ -7,8 +7,18 @@
package org.hibernate.spatial.testing.dialects.sqlserver;
import java.util.List;
import java.util.Map;
import org.hibernate.spatial.CommonSpatialFunction;
import org.hibernate.spatial.GeomCodec;
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.geolatte.geom.Geometry;
import org.geolatte.geom.codec.db.sqlserver.Decoders;
/**
* @author Karel Maesen, Geovise BVBA
@ -21,8 +31,40 @@ public class SQLServerTestSupport extends TestSupport {
return TestData.fromFile( "test-data-set.xml" );
}
public SqlServerExpectationsFactory createExpectationsFactory() {
return new SqlServerExpectationsFactory();
@Override
public NativeSQLTemplates templates() {
return new SqlServerNativeSqlTemplates();
}
@Override
public PredicateRegexes predicateRegexes() {
return new SqlServerPredicateRegexes();
}
@Override
public Map<CommonSpatialFunction, String> hqlOverrides() {
return super.hqlOverrides();
}
@Override
public List<CommonSpatialFunction> getExcludeFromTests() {
//ST_Relate implementation is inconsistent accross dialects
//TODO -- re-enable when inconsistency is resolved
return List.of( CommonSpatialFunction.ST_RELATE );
}
@Override
public GeomCodec codec() {
return new GeomCodec() {
@Override
public Geometry<?> toGeometry(Object in) {
return Decoders.decode( (byte[]) in );
}
};
}
@Override
public Geometry<?> getFilterGeometry() {
return super.getFilterGeometry();
}
}

View File

@ -1,234 +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.testing.dialects.sqlserver;
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.NativeSQLStatement;
import org.geolatte.geom.codec.db.sqlserver.Decoders;
import org.geolatte.geom.jts.JTS;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
/**
* Implementation of an <code>AbstractExpectationsFactory</code>
* for Microsoft SQL Server (2008).
*/
public class SqlServerExpectationsFactory extends AbstractExpectationsFactory {
public SqlServerExpectationsFactory() {
super();
}
@Override
public NativeSQLStatement createNativeDimensionSQL() {
return createNativeSQLStatement( "select t.id, t.geom.STDimension() from GeomTest t" );
}
@Override
public NativeSQLStatement createNativeBufferStatement(Double distance) {
return createNativeSQLStatement(
"select t.id, t.geom.STBuffer(?) from GeomTest t where t.geom.STSrid = 4326",
new Object[] { distance }
);
}
@Override
public NativeSQLStatement createNativeConvexHullStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STUnion(geometry::STGeomFromText(?, 4326)).STConvexHull() from GeomTest t where t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeIntersectionStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STIntersection(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeDifferenceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STDifference(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeSymDifferenceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STSymDifference(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeGeomUnionStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STUnion(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeAsTextStatement() {
return createNativeSQLStatement( "select t.id, t.geom.STAsText() from GeomTest t" );
}
@Override
public NativeSQLStatement createNativeSridStatement() {
return createNativeSQLStatement( "select t.id, t.geom.STSrid from GeomTest t" );
}
@Override
public NativeSQLStatement createNativeIsSimpleStatement() {
return createNativeSQLStatement( "select t.id, t.geom.STIsSimple() from GeomTest t" );
}
@Override
public NativeSQLStatement createNativeIsEmptyStatement() {
return createNativeSQLStatement( "select t.id, t.geom.STIsEmpty() from GeomTest t" );
}
@Override
public NativeSQLStatement createNativeIsNotEmptyStatement() {
return createNativeSQLStatement( "select t.id, ~t.geom.STIsEmpty() from GeomTest t" );
}
@Override
public NativeSQLStatement createNativeBoundaryStatement() {
return createNativeSQLStatement( "select t.id, t.geom.STBoundary() from GeomTest t" );
}
@Override
public NativeSQLStatement createNativeEnvelopeStatement() {
return createNativeSQLStatement( "select t.id, t.geom.STEnvelope() from GeomTest t" );
}
@Override
public NativeSQLStatement createNativeAsBinaryStatement() {
return createNativeSQLStatement( "select t.id, t.geom.STAsBinary() from GeomTest t" );
}
@Override
public NativeSQLStatement createNativeGeometryTypeStatement() {
return createNativeSQLStatement( "select t.id, t.geom.STGeometryType() from GeomTest t" );
}
@Override
protected Geometry decode(Object o) {
return JTS.to( Decoders.decode( (byte[]) o ) );
}
@Override
public NativeSQLStatement createNativeWithinStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STWithin(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STWithin(geometry::STGeomFromText(?, 4326)) = 'true' and t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeEqualsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STEquals(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STEquals(geometry::STGeomFromText(?, 4326)) = 'true' and t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeCrossesStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STCrosses(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STCrosses(geometry::STGeomFromText(?, 4326)) = 'true' and t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeContainsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STContains(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STContains(geometry::STGeomFromText(?, 4326)) = 'true' and t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeDisjointStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STDisjoint(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STDisjoint(geometry::STGeomFromText(?, 4326)) = 'true' and t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeTransformStatement(int epsg) {
throw new UnsupportedOperationException();
}
@Override
public NativeSQLStatement createNativeHavingSRIDStatement(int srid) {
return createNativeSQLStatement( "select t.id, 1 from GeomTest t where t.geom.STSrid = " + srid );
}
@Override
public NativeSQLStatement createNativeIntersectsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STIntersects(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STIntersects(geometry::STGeomFromText(?, 4326)) = 'true' and t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeFilterStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.Filter(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.Filter(geometry::STGeomFromText(?, 4326)) = 1 and t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeTouchesStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STTouches(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STTouches(geometry::STGeomFromText(?, 4326)) = 'true' and t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeOverlapsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STOverlaps(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STOverlaps(geometry::STGeomFromText(?, 4326)) = 'true' and t.geom.STSrid = 4326",
geom.toText()
);
}
@Override
public NativeSQLStatement createNativeRelateStatement(Geometry geom, String matrix) {
String sql = "select t.id, t.geom.STRelate(geometry::STGeomFromText(?, 4326), '" + matrix + "' ) from GeomTest t where t.geom.STRelate(geometry::STGeomFromText(?, 4326), '" + matrix + "') = 'true' and t.geom.STSrid = 4326";
return createNativeSQLStatementAllWKTParams( sql, geom.toText() );
}
@Override
public NativeSQLStatement createNativeDwithinStatement(Point geom, double distance) {
throw new UnsupportedOperationException();
}
@Override
public NativeSQLStatement createNativeDistanceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.STDistance(geometry::STGeomFromText(?, 4326)) from GeomTest t where t.geom.STSrid = 4326",
geom.toText()
);
}
}

View File

@ -0,0 +1,84 @@
/*
* 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.sqlserver;
import org.hibernate.spatial.testing.dialects.NativeSQLTemplates;
import static org.hibernate.spatial.CommonSpatialFunction.ST_ASBINARY;
import static org.hibernate.spatial.CommonSpatialFunction.ST_ASTEXT;
import static org.hibernate.spatial.CommonSpatialFunction.ST_BOUNDARY;
import static org.hibernate.spatial.CommonSpatialFunction.ST_BUFFER;
import static org.hibernate.spatial.CommonSpatialFunction.ST_CONTAINS;
import static org.hibernate.spatial.CommonSpatialFunction.ST_CONVEXHULL;
import static org.hibernate.spatial.CommonSpatialFunction.ST_CROSSES;
import static org.hibernate.spatial.CommonSpatialFunction.ST_DIFFERENCE;
import static org.hibernate.spatial.CommonSpatialFunction.ST_DIMENSION;
import static org.hibernate.spatial.CommonSpatialFunction.ST_DISJOINT;
import static org.hibernate.spatial.CommonSpatialFunction.ST_DISTANCE;
import static org.hibernate.spatial.CommonSpatialFunction.ST_ENVELOPE;
import static org.hibernate.spatial.CommonSpatialFunction.ST_EQUALS;
import static org.hibernate.spatial.CommonSpatialFunction.ST_GEOMETRYTYPE;
import static org.hibernate.spatial.CommonSpatialFunction.ST_INTERSECTION;
import static org.hibernate.spatial.CommonSpatialFunction.ST_INTERSECTS;
import static org.hibernate.spatial.CommonSpatialFunction.ST_ISEMPTY;
import static org.hibernate.spatial.CommonSpatialFunction.ST_ISSIMPLE;
import static org.hibernate.spatial.CommonSpatialFunction.ST_OVERLAPS;
import static org.hibernate.spatial.CommonSpatialFunction.ST_RELATE;
import static org.hibernate.spatial.CommonSpatialFunction.ST_SRID;
import static org.hibernate.spatial.CommonSpatialFunction.ST_SYMDIFFERENCE;
import static org.hibernate.spatial.CommonSpatialFunction.ST_TOUCHES;
import static org.hibernate.spatial.CommonSpatialFunction.ST_UNION;
import static org.hibernate.spatial.CommonSpatialFunction.ST_WITHIN;
public class SqlServerNativeSqlTemplates extends NativeSQLTemplates {
public SqlServerNativeSqlTemplates() {
sqls.put( ST_ASTEXT, "select id, geom.STAsText() as result from %s" );
sqls.put( ST_GEOMETRYTYPE, "select id, geom.STGeometryType() as result from %s" );
sqls.put( ST_DIMENSION, "select id, geom.STDimension() as result from %s" );
sqls.put( ST_ENVELOPE, "select id, geom.STEnvelope() as result from %s" );
sqls.put( ST_SRID, "select id, geom.STSrid as result from %s" );
sqls.put( ST_ASBINARY, "select id, geom.STAsBinary() as result from %s" );
sqls.put( ST_ISEMPTY, "select id, geom.STIsEmpty() as result from %s" );
sqls.put( ST_ISSIMPLE, "select id, geom.STIsSimple() as result from %s" );
sqls.put( ST_BOUNDARY, "select id, geom.STBoundary() as result from %s" );
sqls.put(
ST_OVERLAPS,
"select id, geom.STOverlaps(geometry::::STGeomFromText(:filter, 4326)) as result from %s"
);
sqls.put(
ST_INTERSECTS,
"select id, geom.STIntersects(geometry::::STGeomFromText(:filter, 4326)) as result from %s"
);
sqls.put( ST_CROSSES,
"select id, geom.STCrosses(geometry::::STGeomFromText(:filter, 4326)) as result from %s"
);
sqls.put( ST_CONTAINS, "select id, geom.STContains(geometry::::STGeomFromText(:filter, 4326)) as result from %s" );
sqls.put( ST_DISJOINT, "select id, geom.STDisjoint(geometry::::STGeomFromText(:filter, 4326)) as result from %s" );
//TODO -- re-enable once the ST_Relate() mess is resolved
// sqls.put( ST_RELATE, "select id, geom.STRelate(geometry::::STGeomFromText(:filter, 4326), 'FF*FF****') as result from %s" );
sqls.put( ST_TOUCHES, "select id, geom.STTouches(geometry::::STGeomFromText(:filter, 4326)) as result from %s" );
sqls.put( ST_WITHIN, "select id, geom.STWithin(geometry::::STGeomFromText(:filter, 4326)) as result from %s" );
sqls.put( ST_EQUALS, "select id, geom.STEquals(geometry::::STGeomFromText(:filter, 4326)) as result from %s" );
sqls.put( ST_DISTANCE, "select id, geom.STDistance(geometry::::STGeomFromText(:filter, 4326)) as result from %s" );
sqls.put( ST_BUFFER, "select id, geom.STBuffer(2.0) as result from %s" );
sqls.put( ST_CONVEXHULL, "select id, geom.STConvexHull() as result from %s" );
sqls.put( ST_DIFFERENCE, "select id, geom.STDifference(geometry::::STGeomFromText(:filter, 4326)) as result from %s" );
sqls.put(
ST_INTERSECTION,
"select id, geom.STIntersection(geometry::::STGeomFromText(:filter, 4326)) as result from %s"
);
sqls.put(
ST_SYMDIFFERENCE,
"select id, geom.STSymDifference(geometry::::STGeomFromText(:filter, 4326)) as result from %s"
);
sqls.put( ST_UNION, "select id, geom.STUnion(geometry::::STGeomFromText(:filter, 4326)) as result from %s");
}
}

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.testing.dialects.sqlserver;
import org.hibernate.spatial.testing.dialects.PredicateRegexes;
public class SqlServerPredicateRegexes extends PredicateRegexes {
public SqlServerPredicateRegexes() {
super( null );
add(
"overlaps",
"select .* from .* where .*\\.geom\\.stoverlaps\\(.*\\)\\s*=.*"
);
add(
"crosses",
"select .* from .* where .*\\.geom\\.stcrosses\\(.*\\)\\s*=.*"
);
add(
"contains",
"select .* from .* where .*\\.geom\\.stcontains\\(.*\\)\\s*=.*"
);
add(
"disjoint",
"select .* from .* where .*\\.geom\\.stdisjoint\\(.*\\)\\s*=.*"
);
add(
"touches",
"select .* from .* where .*\\.geom\\.sttouches\\(.*\\)\\s*=.*"
);
add(
"within",
"select .* from .* where .*\\.geom\\.stwithin\\(.*\\)\\s*=.*"
);
add(
"intersects",
"select .* from .* where .*\\.geom\\.stintersects\\(.*\\)\\s*=.*"
);
add(
"eq",
"select .* from .* where .*\\.geom\\.stequals\\(.*\\)\\s*=.*"
);
}
}

View File

@ -49,15 +49,15 @@ hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFa
#hibernate.connection.url jdbc:oracle:thin:@localhost:1521:XE
#hibernate.connection.username SYSTEM
#hibernate.connection.password Oracle18
#
##
## MS SQL Server dialect
##
#hibernate.dialect org.hibernate.spatial.dialect.sqlserver.SqlServer2008SpatialDialect
#hibernate.dialect org.hibernate.dialect.SQLServerDialect
#hibernate.connection.driver_class com.microsoft.sqlserver.jdbc.SQLServerDriver
#hibernate.connection.url jdbc:sqlserver://localhost:1433;databaseName=TestDb
#hibernate.connection.username hibern8
#hibernate.connection.password hibern8Pass
#hibernate.connection.url jdbc:sqlserver://localhost;databaseName=hibernate_orm_test
#hibernate.connection.username sa
#hibernate.connection.password Hibernate_orm_test
##
## MySQL
##
@ -67,22 +67,6 @@ hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFa
#hibernate.connection.username hibernate_orm_test
#hibernate.connection.password hibernate_orm_test
##
## MySQL 5 InnoDDB dialect
##
#hibernate.dialect org.hibernate.spatial.dialect.mysql.MySQL56SpatialDialect
#hibernate.connection.driver_class com.mysql.jdbc.Driver
#hibernate.connection.url jdbc:mysql://localhost/testhbs
#hibernate.connection.username hibernate
#hibernate.connection.password hibernate
##
## MySQL 5.6.1 dialect
##
#hibernate.dialect org.hibernate.spatial.dialect.mysql.MySQL56InnoDBSpatialDialect
#hibernate.connection.driver_class com.mysql.jdbc.Driver
#hibernate.connection.url jdbc:mysql://hibernate-spatial-integration.cctaez8ywvn2.eu-west-1.rds.amazonaws.com:3306/test
#hibernate.connection.username hbs
#hibernate.connection.password
##
## HANA dialect
##
#hibernate.dialect org.hibernate.spatial.dialect.hana.HANASpatialDialect