HHH-15047 Ensure spatial functions have non-null return type resolver

This commit is contained in:
Karel Maesen 2022-01-23 15:49:05 +01:00
parent 6590727698
commit 610446270e
7 changed files with 127 additions and 31 deletions

View File

@ -36,7 +36,7 @@ public class BaseSqmFunctionDescriptors implements KeyedSqmFunctionDescriptors {
for ( CommonSpatialFunction func : filter( CommonSpatialFunction.values() ) ) { for ( CommonSpatialFunction func : filter( CommonSpatialFunction.values() ) ) {
final FunctionReturnTypeResolver returnTypeResolver; final FunctionReturnTypeResolver returnTypeResolver;
if ( func.getReturnType() == null ) { if ( func.getReturnType() == null ) {
returnTypeResolver = null; returnTypeResolver = StandardFunctionReturnTypeResolvers.useFirstNonNull();
} }
else { else {
returnTypeResolver = StandardFunctionReturnTypeResolvers.invariant( returnTypeResolver = StandardFunctionReturnTypeResolvers.invariant(

View File

@ -65,7 +65,7 @@ public class OracleSDOFunctionDescriptors implements KeyedSqmFunctionDescriptors
"SDO_GEOM.SDO_MBR", "SDO_GEOM.SDO_MBR",
true, true,
StandardArgumentsValidators.exactly( 1 ), StandardArgumentsValidators.exactly( 1 ),
null StandardFunctionReturnTypeResolvers.useFirstNonNull()
) )
); );
@ -125,7 +125,7 @@ public class OracleSDOFunctionDescriptors implements KeyedSqmFunctionDescriptors
"ST_BOUNDARY", "ST_BOUNDARY",
"ST_BOUNDARY", "ST_BOUNDARY",
1, 1,
null, StandardFunctionReturnTypeResolvers.useFirstNonNull(),
true true
) )
); );
@ -196,7 +196,7 @@ public class OracleSDOFunctionDescriptors implements KeyedSqmFunctionDescriptors
"SDO_GEOM.SDO_BUFFER", "SDO_GEOM.SDO_BUFFER",
true, true,
StandardArgumentsValidators.exactly( 2 ), StandardArgumentsValidators.exactly( 2 ),
null StandardFunctionReturnTypeResolvers.useFirstNonNull()
) )
); );
@ -206,7 +206,7 @@ public class OracleSDOFunctionDescriptors implements KeyedSqmFunctionDescriptors
"SDO_GEOM.SDO_CONVEXHULL", "SDO_GEOM.SDO_CONVEXHULL",
true, true,
StandardArgumentsValidators.exactly( 1 ), StandardArgumentsValidators.exactly( 1 ),
null StandardFunctionReturnTypeResolvers.useFirstNonNull()
) )
); );
@ -216,7 +216,7 @@ public class OracleSDOFunctionDescriptors implements KeyedSqmFunctionDescriptors
"SDO_GEOM.SDO_DIFFERENCE", "SDO_GEOM.SDO_DIFFERENCE",
true, true,
StandardArgumentsValidators.exactly( 2 ), StandardArgumentsValidators.exactly( 2 ),
null StandardFunctionReturnTypeResolvers.useFirstNonNull()
) )
); );
@ -226,7 +226,7 @@ public class OracleSDOFunctionDescriptors implements KeyedSqmFunctionDescriptors
"SDO_GEOM.SDO_INTERSECTION", "SDO_GEOM.SDO_INTERSECTION",
true, true,
StandardArgumentsValidators.exactly( 2 ), StandardArgumentsValidators.exactly( 2 ),
null StandardFunctionReturnTypeResolvers.useFirstNonNull()
) )
); );
@ -236,7 +236,7 @@ public class OracleSDOFunctionDescriptors implements KeyedSqmFunctionDescriptors
"SDO_GEOM.SDO_XOR", "SDO_GEOM.SDO_XOR",
true, true,
StandardArgumentsValidators.exactly( 2 ), StandardArgumentsValidators.exactly( 2 ),
null StandardFunctionReturnTypeResolvers.useFirstNonNull()
) )
); );
@ -246,7 +246,7 @@ public class OracleSDOFunctionDescriptors implements KeyedSqmFunctionDescriptors
"SDO_GEOM.SDO_UNION", "SDO_GEOM.SDO_UNION",
true, true,
StandardArgumentsValidators.exactly( 2 ), StandardArgumentsValidators.exactly( 2 ),
null StandardFunctionReturnTypeResolvers.useFirstNonNull()
) )
); );

View File

@ -9,14 +9,11 @@ package org.hibernate.spatial.dialect.oracle;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import org.hibernate.boot.model.FunctionContributions; 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.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.spatial.CommonSpatialFunction; import org.hibernate.spatial.CommonSpatialFunction;
import org.hibernate.spatial.FunctionKey; import org.hibernate.spatial.FunctionKey;
@ -52,7 +49,7 @@ public class OracleSQLMMFunctionDescriptors implements KeyedSqmFunctionDescripto
addSTFunction( CommonSpatialFunction.ST_WITHIN, StandardBasicTypes.BOOLEAN ); addSTFunction( CommonSpatialFunction.ST_WITHIN, StandardBasicTypes.BOOLEAN );
addSTFunction( CommonSpatialFunction.ST_EQUALS, StandardBasicTypes.BOOLEAN ); addSTFunction( CommonSpatialFunction.ST_EQUALS, StandardBasicTypes.BOOLEAN );
addSTFunction( CommonSpatialFunction.ST_DISTANCE, StandardBasicTypes.DOUBLE ); addSTFunction( CommonSpatialFunction.ST_DISTANCE, StandardBasicTypes.DOUBLE );
addSTFunction( CommonSpatialFunction.ST_RELATE, new STRelateFunction( typeRegistry ) ); addSTRelateFunction();
addSTFunction( CommonSpatialFunction.ST_DIFFERENCE ); addSTFunction( CommonSpatialFunction.ST_DIFFERENCE );
addSTFunction( CommonSpatialFunction.ST_INTERSECTION ); addSTFunction( CommonSpatialFunction.ST_INTERSECTION );
addSTFunction( CommonSpatialFunction.ST_SYMDIFFERENCE ); addSTFunction( CommonSpatialFunction.ST_SYMDIFFERENCE );
@ -78,7 +75,13 @@ public class OracleSQLMMFunctionDescriptors implements KeyedSqmFunctionDescripto
private void addSTFunction(CommonSpatialFunction func, String stMethod) { private void addSTFunction(CommonSpatialFunction func, String stMethod) {
map.put( map.put(
func.getKey(), func.getKey(),
new OracleSpatialSQLMMFunction( func.getKey().getName(), stMethod, func.getNumArgs(), null, true ) new OracleSpatialSQLMMFunction(
func.getKey().getName(),
stMethod,
func.getNumArgs(),
StandardFunctionReturnTypeResolvers.useFirstNonNull(),
true
)
); );
} }
@ -90,12 +93,11 @@ public class OracleSQLMMFunctionDescriptors implements KeyedSqmFunctionDescripto
addSTFunction( func, func.getKey().getName().toUpperCase( Locale.ROOT ) ); addSTFunction( func, func.getKey().getName().toUpperCase( Locale.ROOT ) );
} }
private void addSTFunction(CommonSpatialFunction func, OracleSpatialFunction descriptor) { private void addSTRelateFunction() {
map.put( func.getKey(), descriptor ); map.put( CommonSpatialFunction.ST_RELATE.getKey(), new STRelateFunction( typeRegistry ) );
} }
@Override @Override
public Map<FunctionKey, SqmFunctionDescriptor> asMap() { public Map<FunctionKey, SqmFunctionDescriptor> asMap() {
return Collections.unmodifiableMap( map ); return Collections.unmodifiableMap( map );

View File

@ -0,0 +1,97 @@
/*
* 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.integration.functions;
import java.util.List;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.query.Query;
import org.hibernate.spatial.testing.SpatialTestBase;
import org.hibernate.spatial.testing.datareader.TestSupport;
import org.hibernate.spatial.testing.domain.GeomEntity;
import org.hibernate.spatial.testing.domain.JtsGeomEntity;
import org.hibernate.spatial.testing.domain.SpatialDomainModel;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.RequiresDialects;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
@DomainModel(modelDescriptorClasses = SpatialDomainModel.class)
@SessionFactory
@RequiresDialects({
@RequiresDialect(PostgreSQLDialect.class),
@RequiresDialect(H2Dialect.class)
})
public class BasicFunctionTest extends SpatialTestBase {
@Test
public void testJTS() {
scope.inTransaction( (session) -> {
Query<?> query = session.createQuery(
"select st_convexhull(geom) from JtsGeomEntity",
org.locationtech.jts.geom.Geometry.class
);
List<?> results = query.getResultList();
assertFalse( results.isEmpty() );
assertInstanceOf( org.locationtech.jts.geom.Geometry.class, results.get( 0 ) );
} );
}
@Override
public TestSupport.TestDataPurpose purpose() {
return TestSupport.TestDataPurpose.SpatialFunctionsData;
}
@Test
public void testGeolatte() {
scope.inTransaction( (session) -> {
Query<?> query = session.createQuery(
"select st_convexhull(e.geom) from GeomEntity e",
org.geolatte.geom.Geometry.class
);
List<?> results = query.getResultList();
assertFalse( results.isEmpty() );
assertInstanceOf( org.geolatte.geom.Geometry.class, results.get( 0 ) );
} );
}
@Test
public void testJtsIntersectsParam() {
scope.inTransaction( (session) -> {
Query<JtsGeomEntity> query = session.createQuery(
"select g from JtsGeomEntity g where st_intersects(g.geom, st_boundary(:poly) ) = true",
JtsGeomEntity.class
);
query.setParameter( "poly", org.geolatte.geom.jts.JTS.to( filterGeometry ) );
List<?> results = query.getResultList();
assertFalse( results.isEmpty() );
} );
}
@Test
public void testGeolatteIntersectsParam() {
scope.inTransaction( (session) -> {
Query<GeomEntity> query = session.createQuery(
"select g from GeomEntity g where st_intersects(g.geom, st_boundary(:poly) ) = true",
GeomEntity.class
);
query.setParameter( "poly", filterGeometry );
List<?> results = query.getResultList();
assertFalse( results.isEmpty() );
} );
}
}

View File

@ -17,7 +17,7 @@ import java.util.Objects;
public interface RowObjectMapper<T> { public interface RowObjectMapper<T> {
default Data apply(Object obj) { default Data apply(Object obj) {
Object[] row = (Object[]) obj; Object[] row = (Object[]) obj;
return new Data( (Number) row[0], (T) row[1] ); return new Data( (Number) row[0], row[1] );
} }
} }
@ -64,6 +64,7 @@ class Data {
return "Data{" + return "Data{" +
"id=" + id + "id=" + id +
", datum=" + datum + ", datum=" + datum +
" (" + datum.getClass().getCanonicalName() + ")" +
'}'; '}';
} }
} }

View File

@ -26,7 +26,6 @@ import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.Executable;
@RequiresDialectFeature(feature = IsSupportedBySpatial.class) @RequiresDialectFeature(feature = IsSupportedBySpatial.class)
@SessionFactory @SessionFactory
public class TestGeometryConstructionWithParameter extends SpatialTestBase { public class TestGeometryConstructionWithParameter extends SpatialTestBase {
@ -61,8 +60,8 @@ public class TestGeometryConstructionWithParameter extends SpatialTestBase {
@TestFactory @TestFactory
public Stream<DynamicTest> testFunctions() { public Stream<DynamicTest> testFunctions() {
return Arrays.stream( CommonSpatialFunction.values() ) return Arrays.stream( CommonSpatialFunction.values() )
.filter( f -> f.getType() == CommonSpatialFunction.Type.CONSTRUCTION && isSupported( f ) && templateAvailable( .filter( f -> f.getType() == CommonSpatialFunction.Type.CONSTRUCTION && isSupported( f )
f ) ) && templateAvailable( f ) )
.map( this::buildTestFunction ); .map( this::buildTestFunction );
} }
@ -72,14 +71,12 @@ public class TestGeometryConstructionWithParameter extends SpatialTestBase {
} }
private Executable buildExec(final CommonSpatialFunction func) { private Executable buildExec(final CommonSpatialFunction func) {
return () -> { return () -> scope.inSession( session -> {
scope.inSession( session -> { String hql = templates.get( func );
String hql = templates.get( func ); hql = adaptToDialect( session, hql );
hql = adaptToDialect( session, hql ); session.createQuery( hql, GeomEntity.class ).setParameter( "poly", filterGeometry ).getResultList();
session.createQuery( hql, GeomEntity.class ).setParameter( "poly", filterGeometry ).getResultList(); //we just check that this parses for now.
//we just check that this parses for now. } );
} );
};
} }
private String adaptToDialect(SessionImplementor session, String hql) { private String adaptToDialect(SessionImplementor session, String hql) {
@ -96,6 +93,6 @@ public class TestGeometryConstructionWithParameter extends SpatialTestBase {
} }
private boolean templateAvailable(CommonSpatialFunction f) { private boolean templateAvailable(CommonSpatialFunction f) {
return templates.keySet().contains( f ); return templates.containsKey( f );
} }
} }

View File

@ -37,7 +37,6 @@ import static org.geolatte.geom.crs.CoordinateReferenceSystems.WGS84;
* @author Karel Maesen, Geovise BVBA * @author Karel Maesen, Geovise BVBA
* creation-date: Sep 30, 2010 * creation-date: Sep 30, 2010
*/ */
@Deprecated
public abstract class TestSupport { public abstract class TestSupport {
//TODO -- make this abstract //TODO -- make this abstract