HHH-14807 Upgrade SpatialPredicates for Oracle

This commit is contained in:
Karel Maesen 2022-01-21 14:46:26 +01:00 committed by Steve Ebersole
parent d560d81988
commit cbf98a1845
17 changed files with 127 additions and 276 deletions

View File

@ -1,28 +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;
/**
* Enumeration of types of Spatial Aggregation
*
* @author Karel Maesen
* @deprecated Will be removed in 6.0
*/
@Deprecated
public interface SpatialAggregate {
/**
* Enum value for extent aggregation.
*/
public static final int EXTENT = 1;
/**
* Enum value for union aggregate (only supported in DB2)
*/
public static final int UNION = 2;
}

View File

@ -1,53 +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;
/**
* The spatial analysis functions defined in the OGC SFS specification.
*
* @author Karel Maesen
* @deprecated Will be removed in 6
*/
@Deprecated
public interface SpatialAnalysis {
/**
* The distance function
*/
public static int DISTANCE = 1;
/**
* The buffer function
*/
public static int BUFFER = 2;
/**
* The convexhull function
*/
public static int CONVEXHULL = 3;
/**
* The intersection function
*/
public static int INTERSECTION = 4;
/**
* The union function
*/
public static int UNION = 5;
/**
* The difference function
*/
public static int DIFFERENCE = 6;
/**
* The symmetric difference function
*/
public static int SYMDIFFERENCE = 7;
}

View File

@ -1,37 +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;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
/**
* Registers all available spatial functions for a <code>Dialect</code>
* <p>
* Created by Karel Maesen, Geovise BVBA on 29/10/16.
* @Deprecated Use KeyedSqmFunctionDescriptors
*/
public abstract class SpatialFunctionsRegistry implements Iterable<Map.Entry<String, SqmFunctionDescriptor>>, Serializable {
protected final Map<String, SqmFunctionDescriptor> functionMap = new HashMap<String, SqmFunctionDescriptor>();
public void put(String name, SqmFunctionDescriptor function) {
this.functionMap.put( name, function );
}
@Override
public Iterator<Map.Entry<String, SqmFunctionDescriptor>> iterator() {
return functionMap.entrySet().iterator();
}
public SqmFunctionDescriptor get(String functionName) {
return functionMap.get( functionName );
}
}

View File

@ -1,18 +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;
/**
* An Interface for {@code SpatialDialect}s that require a custom
* rendering to JPAQL for the filter predicate
* <p>
* Created by Karel Maesen, Geovise BVBA on 09/02/2020.
*/
public interface WithCustomJPAFilter {
String filterExpression(String geometryParam, String filterParam);
}

View File

@ -25,9 +25,16 @@ import org.geolatte.geom.codec.db.oracle.OracleJDBCTypeFactory;
public class OracleDialectContributor implements ContributorImplementor {
private final ServiceRegistry serviceRegistry;
private final boolean useSTGeometry;
public OracleDialectContributor(ServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry;
final var cfgService = getServiceRegistry().getService( ConfigurationService.class );
this.useSTGeometry = cfgService.getSetting(
HibernateSpatialConfigurationSettings.ORACLE_OGC_STRICT,
StandardConverters.BOOLEAN,
false
);
}
@Override
@ -36,6 +43,7 @@ public class OracleDialectContributor implements ContributorImplementor {
final ConfigurationService cfgService = getServiceRegistry().getService( ConfigurationService.class );
final StrategySelector strategySelector = getServiceRegistry().getService( StrategySelector.class );
final ConnectionFinder connectionFinder = strategySelector.resolveStrategy(
ConnectionFinder.class,
cfgService.getSetting(
@ -48,27 +56,20 @@ public class OracleDialectContributor implements ContributorImplementor {
HSMessageLogger.LOGGER.connectionFinder( connectionFinder.getClass().getCanonicalName() );
SDOGeometryType sdoGeometryType = new SDOGeometryType(
new OracleJDBCTypeFactory(
connectionFinder
)
new OracleJDBCTypeFactory( connectionFinder ), useSTGeometry
);
typeContributions.contributeJdbcTypeDescriptor( sdoGeometryType );
typeContributions.contributeJdbcType( sdoGeometryType );
}
@Override
public void contributeFunctions(FunctionContributions functionContributions) {
HSMessageLogger.LOGGER.functionContributions( this.getClass().getCanonicalName() );
final var cfgService = getServiceRegistry().getService( ConfigurationService.class );
boolean isOgcStrict = cfgService.getSetting(
HibernateSpatialConfigurationSettings.ORACLE_OGC_STRICT,
StandardConverters.BOOLEAN,
false
);
KeyedSqmFunctionDescriptors functionDescriptors;
if (isOgcStrict)
functionDescriptors = new OracleSQLMMFunctionDescriptors( functionContributions);
if ( useSTGeometry ) {
functionDescriptors = new OracleSQLMMFunctionDescriptors( functionContributions );
}
else {
functionDescriptors = new OracleSDOFunctionDescriptors( functionContributions );
}

View File

@ -1,41 +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.oracle;
/**
* Defines types of Oracle Spatial aggregate functions
*
* @author Karel Maesen, Geovise BVBA
*/
public interface OracleSpatialAggregate extends org.hibernate.spatial.SpatialAggregate {
/**
* LRS_CONCAT aggregate function
*/
public static int LRS_CONCAT = 100;
/**
* CENTROID aggregate function
*/
public static int CENTROID = 101;
/**
* CONCAT_LINES aggregate function
*/
public static int CONCAT_LINES = 102;
/**
* UNION aggregate function
*/
public static int UNION = 103;
/**
* CONVEXHULL aggregate function
*/
public static int CONVEXHULL = 104;
}

View File

@ -68,7 +68,7 @@ public class OracleSpatialSQLMMFunction extends OracleSpatialFunction {
for ( int i = 1; i < arguments.size(); i++ ) {
Expression param = (Expression) arguments.get( i );
if ( param.getExpressionType().getJdbcMappings().get( 0 ).getJdbcTypeDescriptor()
if ( param.getExpressionType().getJdbcMappings().get( 0 ).getJdbcType()
.getDefaultSqlTypeCode() == SqlTypes.GEOMETRY ) {
sqlAppender.appendSql( "ST_GEOMETRY(" );
walker.render( param, SqlAstNodeRenderingMode.DEFAULT);

View File

@ -9,7 +9,6 @@ package org.hibernate.spatial.dialect.oracle;
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;
@ -17,7 +16,6 @@ import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.geolatte.geom.codec.Wkt;
import org.geolatte.geom.codec.db.oracle.OracleJDBCTypeFactory;
/**
@ -28,14 +26,17 @@ import org.geolatte.geom.codec.db.oracle.OracleJDBCTypeFactory;
public class SDOGeometryType implements JdbcType {
private final OracleJDBCTypeFactory typeFactory;
private final boolean useSTGeometry;
/**
* Constructs a {@code SqlTypeDescriptor} for the Oracle SDOGeometry type.
*
* @param typeFactory the type factory to use.
* @param useSTGeometry
*/
public SDOGeometryType(OracleJDBCTypeFactory typeFactory) {
public SDOGeometryType(OracleJDBCTypeFactory typeFactory, boolean useSTGeometry) {
this.typeFactory = typeFactory;
this.useSTGeometry = useSTGeometry;
}
@Override
@ -48,9 +49,10 @@ public class SDOGeometryType 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" );
return new OracleJdbcLiteralFormatter<>( javaTypeDescriptor );
}
@Override

View File

@ -0,0 +1,38 @@
/*
* 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.oracle;
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;
class OracleJdbcLiteralFormatter<T> implements JdbcLiteralFormatter<T> {
private final JavaType<T> javaType;
OracleJdbcLiteralFormatter(JavaType<T> javaType) {
this.javaType = javaType;
}
@Override
public void appendJdbcLiteral(
SqlAppender appender, T value, Dialect dialect, WrapperOptions wrapperOptions) {
Geometry<?> geom = javaType.unwrap( value, Geometry.class, wrapperOptions );
appender.appendSql( "ST_GEOMETRY.FROM_WKT" );
appender.appendSql( "('" );
appender.appendSql( Wkt.toWkt( geom, Wkt.Dialect.SFA_1_2_1 ) );
appender.appendSql( "'," );
appender.appendSql( ( Math.max( geom.getSRID(), 0 ) ) );
appender.appendSql( ").Geom" );
}
}

View File

@ -1,68 +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.oracle;
/**
* Provides Aggregate type spatial function interpretation
*/
class SpatialAggregateImpl {
private static final String SDO_AGGR = "SDO_AGGR_";
private boolean aggregateType;
private String aggregateSyntax;
SpatialAggregateImpl() {
}
SpatialAggregateImpl(int aggregation) {
String specificAggrSyntax;
switch ( aggregation ) {
case org.hibernate.spatial.SpatialAggregate.EXTENT:
specificAggrSyntax = "MBR";
aggregateType = false;
break;
case OracleSpatialAggregate.LRS_CONCAT:
specificAggrSyntax = "LRS_CONCAT";
aggregateType = true;
break;
case OracleSpatialAggregate.CENTROID:
specificAggrSyntax = "CENTROID";
aggregateType = true;
break;
case OracleSpatialAggregate.CONCAT_LINES:
specificAggrSyntax = "CONCAT_LINES";
aggregateType = false;
break;
case OracleSpatialAggregate.UNION:
specificAggrSyntax = "UNION";
aggregateType = true;
break;
case OracleSpatialAggregate.CONVEXHULL:
specificAggrSyntax = "CONVEXHULL";
aggregateType = true;
break;
default:
specificAggrSyntax = null;
break;
}
if ( specificAggrSyntax != null ) {
aggregateSyntax = SDO_AGGR + specificAggrSyntax;
}
}
public boolean isAggregateType() {
return aggregateType;
}
public String getAggregateSyntax() {
return aggregateSyntax;
}
}

View File

@ -7,14 +7,10 @@
package org.hibernate.spatial.dialect.sqlserver;
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
/**
* Created by Karel Maesen, Geovise BVBA on 19/09/2018.
*/
class SqlServerFunctions extends SpatialFunctionsRegistry {
class SqlServerFunctions{
public SqlServerFunctions() {
//TODO -- re-implement. In 6.0 there is no longer a SQLFunctionTemplate class

View File

@ -22,10 +22,10 @@ import org.hibernate.spatial.SpatialRelation;
class SqlServerSupport implements SpatialDialect, Serializable {
private SqlServerFunctions functions = new SqlServerFunctions();
Iterable<? extends Map.Entry<String, SqmFunctionDescriptor>> functionsToRegister() {
return functions;
}
//
// Iterable<? extends Map.Entry<String, SqmFunctionDescriptor>> functionsToRegister() {
// return functions;
// }
void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
}
@ -100,7 +100,7 @@ class SqlServerSupport implements SpatialDialect, Serializable {
public boolean supports(SpatialFunction function) {
return ( functions.get( function.toString() ) != null );
return true;
}
}

View File

@ -10,6 +10,7 @@ package org.hibernate.spatial.integration.predicates;
import java.util.stream.Stream;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.spatial.HibernateSpatialConfigurationSettings;
import org.hibernate.spatial.testing.IsSupportedBySpatial;
import org.hibernate.spatial.testing.dialects.PredicateRegexes;
@ -20,7 +21,8 @@ import org.hibernate.testing.orm.junit.Setting;
@RequiresDialectFeature(feature = IsSupportedBySpatial.class)
@ServiceRegistry(settings = {
@Setting(name = AvailableSettings.CRITERIA_VALUE_HANDLING_MODE, value = "BIND")
@Setting(name = AvailableSettings.CRITERIA_VALUE_HANDLING_MODE, value = "BIND"),
@Setting(name = HibernateSpatialConfigurationSettings.ORACLE_OGC_STRICT, value = "true")
})
@SessionFactory
public class SpatialPredicatesTestBindingMode extends SpatialPredicatesTest {

View File

@ -10,6 +10,7 @@ package org.hibernate.spatial.integration.predicates;
import java.util.stream.Stream;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.spatial.HibernateSpatialConfigurationSettings;
import org.hibernate.spatial.testing.IsSupportedBySpatial;
import org.hibernate.spatial.testing.dialects.PredicateRegexes;
@ -20,7 +21,8 @@ import org.hibernate.testing.orm.junit.Setting;
@RequiresDialectFeature(feature = IsSupportedBySpatial.class)
@ServiceRegistry(settings = {
@Setting(name = AvailableSettings.CRITERIA_VALUE_HANDLING_MODE, value = "INLINE")
@Setting(name = AvailableSettings.CRITERIA_VALUE_HANDLING_MODE, value = "INLINE"),
@Setting(name = HibernateSpatialConfigurationSettings.ORACLE_OGC_STRICT, value = "true")
})
@SessionFactory
public class SpatialPredicatesTestInlineMode extends SpatialPredicatesTest{

View File

@ -80,10 +80,14 @@ public class PredicateRegexes {
.map( mkPredRegex );
}
private void add(String predicate, String inlineRegex, String bindingRegex) {
protected void add(String predicate, String inlineRegex, String bindingRegex) {
regexes.put( predicate, new RegexPair( inlineRegex, bindingRegex ) );
}
protected void add(String predicate, String regex) {
regexes.put( predicate, new RegexPair( regex, regex ) );
}
static public class PredicateRegex {
public final String predicate;
public final String regex;

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.oracle;
import org.hibernate.spatial.testing.dialects.PredicateRegexes;
public class OraclePredicateRegexes extends PredicateRegexes {
public OraclePredicateRegexes() {
super( null );
add(
"overlaps",
"select .* from .* where st_geometry\\(.*\\).st_overlap.*=.*"
);
add(
"crosses",
"select .* from .* where st_geometry\\(.*\\).st_crosses.*=.*"
);
add(
"contains",
"select .* from .* where st_geometry\\(.*\\).st_contains.*=.*"
);
add(
"disjoint",
"select .* from .* where st_geometry\\(.*\\).st_disjoint.*=.*"
);
add(
"touches",
"select .* from .* where st_geometry\\(.*\\).st_touches.*=.*"
);
add(
"within",
"select .* from .* where st_geometry\\(.*\\).st_within.*=.*"
);
add(
"intersects",
"select .* from .* where st_geometry\\(.*\\).st_intersects.*=.*"
);
add(
"eq",
"select .* from .* where st_geometry\\(.*\\).st_equals.*=.*"
);
}
}

View File

@ -33,7 +33,7 @@ public class OracleSDOTestSupport extends TestSupport {
@Override
public PredicateRegexes predicateRegexes() {
return new PredicateRegexes( "st_" );
return new OraclePredicateRegexes();
}
@Override