HHH-7132 - New Oracle Spatial Dialect that is non-OGC compliant

This commit is contained in:
Karel Maesen 2016-03-17 21:42:19 +01:00
parent 550c2e38ff
commit b9ddc063cd
22 changed files with 1016 additions and 462 deletions

View File

@ -7,9 +7,9 @@
hibernate.dialect org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect
hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
hibernate.connection.url jdbc:oracle:thin:@oracle.geovise.com/ORCL
hibernate.connection.username hbs
hibernate.connection.password hbs
hibernate.connection.url jdbc:oracle:thin:@localhost:1521/orcl12c
hibernate.connection.username C##hibernate
hibernate.connection.password hibernate
hibernate.connection.pool_size 5

View File

@ -7,9 +7,9 @@
hibernate.dialect org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect
hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
hibernate.connection.url jdbc:oracle:thin:@ec2-54-216-171-204.eu-west-1.compute.amazonaws.com:1521/ORCL
hibernate.connection.username hibspa
hibernate.connection.password L9un5Bh6
hibernate.connection.url jdbc:oracle:thin:@localhost:1521/orcl12c
hibernate.connection.username C##hibernate
hibernate.connection.password hibernate
## uncommenting this will fail a unit test!!
hibernate.spatial.connection_finder org.hibernate.spatial.dialect.oracle.TestConnectionFinder

View File

@ -7,9 +7,9 @@
hibernate.dialect org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect
hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
hibernate.connection.url jdbc:oracle:thin:@ec2-54-216-171-204.eu-west-1.compute.amazonaws.com:1521/ORCL
hibernate.connection.username hibspa
hibernate.connection.password L9un5Bh6
hibernate.connection.url jdbc:oracle:thin:@localhost:1521/orcl12c
hibernate.connection.username C##hibernate
hibernate.connection.password hibernate
## uncommenting this will fail a unit test!!
#hibernate.spatial.ogc_strict false

View File

@ -0,0 +1,7 @@
/*
* 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>.
*/
jdbcDependency "com.oracle.jdbc:ojdbc6:11.1.0.7.0"

View File

@ -0,0 +1,25 @@
#
# 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.dialect org.hibernate.spatial.dialect.oracle.OracleSpatialSDO10gDialect
hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
hibernate.connection.url jdbc:oracle:thin:@localhost:1521/orcl12c
hibernate.connection.username C##hibernate
hibernate.connection.password hibernate
## uncommenting this will fail a unit test!!
#hibernate.spatial.ogc_strict false
hibernate.connection.pool_size 5
hibernate.show_sql true
hibernate.format_sql true
hibernate.max_fetch_depth 5
hibernate.cache.region_prefix hibernate.test
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory

View File

@ -0,0 +1,7 @@
/*
* 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>.
*/
jdbcDependency "postgresql:postgresql:8.4-701.jdbc4"

View File

@ -0,0 +1,24 @@
#
# 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.test.new_metadata_mappings = true
hibernate.dialect org.hibernate.spatial.dialect.postgis.PostgisPG91Dialect
hibernate.connection.driver_class org.postgresql.Driver
hibernate.connection.url jdbc:postgresql://localhost:5432/hibbrtru
hibernate.connection.username hibbrtru
hibernate.connection.password hibbrtru
hibernate.connection.pool_size 5
hibernate.show_sql true
hibernate.format_sql true
hibernate.max_fetch_depth 5
hibernate.cache.region_prefix hibernate.test
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory

View File

@ -0,0 +1,7 @@
/*
* 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>.
*/
jdbcDependency "postgresql:postgresql:8.4-701.jdbc4"

View File

@ -0,0 +1,24 @@
#
# 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.test.new_metadata_mappings = true
hibernate.dialect org.hibernate.spatial.dialect.postgis.PostgisPG92Dialect
hibernate.connection.driver_class org.postgresql.Driver
hibernate.connection.url jdbc:postgresql://localhost:5432/hibbrtru
hibernate.connection.username hibbrtru
hibernate.connection.password hibbrtru
hibernate.connection.pool_size 5
hibernate.show_sql true
hibernate.format_sql true
hibernate.max_fetch_depth 5
hibernate.cache.region_prefix hibernate.test
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory

View File

@ -0,0 +1,7 @@
/*
* 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>.
*/
jdbcDependency "postgresql:postgresql:8.4-701.jdbc4"

View File

@ -0,0 +1,24 @@
#
# 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.test.new_metadata_mappings = true
hibernate.dialect org.hibernate.spatial.dialect.postgis.PostgisPG93Dialect
hibernate.connection.driver_class org.postgresql.Driver
hibernate.connection.url jdbc:postgresql://localhost:5432/hibbrtru
hibernate.connection.username hibbrtru
hibernate.connection.password hibbrtru
hibernate.connection.pool_size 5
hibernate.show_sql true
hibernate.format_sql true
hibernate.max_fetch_depth 5
hibernate.cache.region_prefix hibernate.test
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory

View File

@ -0,0 +1,7 @@
/*
* 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>.
*/
jdbcDependency "postgresql:postgresql:8.4-701.jdbc4"

View File

@ -0,0 +1,24 @@
#
# 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.test.new_metadata_mappings = true
hibernate.dialect org.hibernate.spatial.dialect.postgis.PostgisPG94Dialect
hibernate.connection.driver_class org.postgresql.Driver
hibernate.connection.url jdbc:postgresql://localhost:5432/hibbrtru
hibernate.connection.username hibbrtru
hibernate.connection.password hibbrtru
hibernate.connection.pool_size 5
hibernate.show_sql true
hibernate.format_sql true
hibernate.max_fetch_depth 5
hibernate.cache.region_prefix hibernate.test
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory

View File

@ -0,0 +1,7 @@
/*
* 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>.
*/
jdbcDependency "postgresql:postgresql:8.4-701.jdbc4"

View File

@ -0,0 +1,24 @@
#
# 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.test.new_metadata_mappings = true
hibernate.dialect org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect
hibernate.connection.driver_class org.postgresql.Driver
hibernate.connection.url jdbc:postgresql://localhost:5432/hibbrtru
hibernate.connection.username hibbrtru
hibernate.connection.password hibbrtru
hibernate.connection.pool_size 5
hibernate.show_sql true
hibernate.format_sql true
hibernate.max_fetch_depth 5
hibernate.cache.region_prefix hibernate.test
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory

View File

@ -0,0 +1,329 @@
/*
* 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 java.io.Serializable;
import org.geolatte.geom.codec.db.oracle.ConnectionFinder;
import org.geolatte.geom.codec.db.oracle.OracleJDBCTypeFactory;
import org.jboss.logging.Logger;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.HibernateSpatialConfigurationSettings;
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;
/**
* SDO Geometry support for Oracle dialects
* <p>
* Created by Karel Maesen, Geovise BVBA on 01/11/16.
*/
class OracleSDOSupport implements SpatialDialect, Serializable {
private static final HSMessageLogger log = Logger.getMessageLogger(
HSMessageLogger.class,
OracleSpatial10gDialect.class.getName()
);
private final boolean isOgcStrict;
private final SpatialFunctionsRegistry sdoFunctions;
OracleSDOSupport(boolean isOgcStrict) {
this.isOgcStrict = isOgcStrict;
this.sdoFunctions = new OracleSpatialFunctions( isOgcStrict, this );
}
SpatialFunctionsRegistry functionsToRegister() {
return this.sdoFunctions;
}
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
final SDOGeometryTypeDescriptor sdoGeometryTypeDescriptor = mkSdoGeometryTypeDescriptor( serviceRegistry );
typeContributions.contributeType( new GeolatteGeometryType( sdoGeometryTypeDescriptor ) );
typeContributions.contributeType( new JTSGeometryType( sdoGeometryTypeDescriptor ) );
}
private SDOGeometryTypeDescriptor mkSdoGeometryTypeDescriptor(ServiceRegistry serviceRegistry) {
final ConfigurationService cfgService = serviceRegistry.getService( ConfigurationService.class );
final StrategySelector strategySelector = serviceRegistry.getService( StrategySelector.class );
final ConnectionFinder connectionFinder = strategySelector.resolveStrategy(
ConnectionFinder.class,
cfgService.getSetting(
HibernateSpatialConfigurationSettings.CONNECTION_FINDER,
String.class,
"org.geolatte.geom.codec.db.oracle.DefaultConnectionFinder"
)
);
log.connectionFinder( connectionFinder.getClass().getCanonicalName() );
return new SDOGeometryTypeDescriptor(
new OracleJDBCTypeFactory(
connectionFinder
)
);
}
/**
* Returns the SQL fragment for the SQL WHERE-clause when parsing
* <code>org.hibernatespatial.criterion.SpatialRelateExpression</code>s
* into prepared statements.
* <p/>
*
* @param columnName The name of the geometry-typed column to which the relation is
* applied
* @param spatialRelation The type of spatial relation (as defined in
* <code>SpatialRelation</code>).
*
* @return SQL fragment {@code SpatialRelateExpression}
*/
@Override
public String getSpatialRelateSQL(String columnName, int spatialRelation) {
String sql = getOGCSpatialRelateSQL( columnName, "?", spatialRelation ) + " = 1";
sql += " and " + columnName + " is not null";
return sql;
}
public String getOGCSpatialRelateSQL(String arg1, String arg2, int spatialRelation) {
final StringBuffer ogcFunction = new StringBuffer( "MDSYS." );
switch ( spatialRelation ) {
case SpatialRelation.INTERSECTS:
ogcFunction.append( "OGC_INTERSECTS" );
break;
case SpatialRelation.CONTAINS:
ogcFunction.append( "OGC_CONTAINS" );
break;
case SpatialRelation.CROSSES:
ogcFunction.append( "OGC_CROSS" );
break;
case SpatialRelation.DISJOINT:
ogcFunction.append( "OGC_DISJOINT" );
break;
case SpatialRelation.EQUALS:
ogcFunction.append( "OGC_EQUALS" );
break;
case SpatialRelation.OVERLAPS:
ogcFunction.append( "OGC_OVERLAP" );
break;
case SpatialRelation.TOUCHES:
ogcFunction.append( "OGC_TOUCH" );
break;
case SpatialRelation.WITHIN:
ogcFunction.append( "OGC_WITHIN" );
break;
default:
throw new IllegalArgumentException(
"Unknown SpatialRelation ("
+ spatialRelation + ")."
);
}
ogcFunction.append( "(" ).append( "MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(" )
.append( arg1 ).append( ")," ).append(
"MDSYS.ST_GEOMETRY.FROM_SDO_GEOM("
).append( arg2 )
.append( ")" ).append( ")" );
return ogcFunction.toString();
}
/**
* Returns the SQL fragment for the SQL WHERE-clause when parsing
* <code>org.hibernatespatial.criterion.SpatialRelateExpression</code>s
* into prepared statements.
* <p/>
*
* @param columnName The name of the geometry-typed column to which the relation is
* applied
* @param spatialRelation The type of spatial relation (as defined in
* <code>SpatialRelation</code>).
*
* @return SQL fragment {@code SpatialRelateExpression}
*/
public String getSDOSpatialRelateSQL(String columnName, int spatialRelation) {
String sql = getNativeSpatialRelateSQL( columnName, "?", spatialRelation ) + " = 1";
sql += " and " + columnName + " is not null";
return sql;
}
String getNativeSpatialRelateSQL(String arg1, String arg2, int spatialRelation) {
String mask;
boolean negate = false;
switch ( spatialRelation ) {
case SpatialRelation.INTERSECTS:
mask = "ANYINTERACT";
break;
case SpatialRelation.CONTAINS:
mask = "CONTAINS+COVERS";
break;
case SpatialRelation.CROSSES:
throw new UnsupportedOperationException(
"Oracle Spatial does't have equivalent CROSSES relationship"
);
case SpatialRelation.DISJOINT:
mask = "ANYINTERACT";
negate = true;
break;
case SpatialRelation.EQUALS:
mask = "EQUAL";
break;
case SpatialRelation.OVERLAPS:
mask = "OVERLAPBDYDISJOINT+OVERLAPBDYINTERSECT";
break;
case SpatialRelation.TOUCHES:
mask = "TOUCH";
break;
case SpatialRelation.WITHIN:
mask = "INSIDE+COVEREDBY";
break;
default:
throw new IllegalArgumentException(
"undefined SpatialRelation passed (" + spatialRelation
+ ")"
);
}
final StringBuilder buffer = new StringBuilder( "CASE SDO_RELATE(" ).append( arg1 )
.append( "," )
.append( arg2 )
.append( ",'mask=" )
.append( mask )
.append( "') " );
if ( !negate ) {
buffer.append( " WHEN 'TRUE' THEN 1 ELSE 0 END" );
}
else {
buffer.append( " WHEN 'TRUE' THEN 0 ELSE 1 END" );
}
return buffer.toString();
}
/**
* Returns the SQL fragment for the SQL WHERE-expression when parsing
* <code>org.hibernate.spatial.criterion.SpatialFilterExpression</code>s
* into prepared statements.
*
* @param columnName The name of the geometry-typed column to which the filter is
* be applied
*
* @return Rhe SQL fragment for the {@code SpatialFilterExpression}
*/
@Override
public String getSpatialFilterExpression(String columnName) {
final StringBuffer buffer = new StringBuffer( "SDO_FILTER(" );
buffer.append( columnName );
buffer.append( ",?) = 'TRUE' " );
return buffer.toString();
}
/**
* Returns the SQL fragment for the specfied Spatial aggregate expression.
*
* @param columnName The name of the Geometry property
* @param aggregation The type of <code>SpatialAggregate</code>
*
* @return The SQL fragment for the projection
*/
@Override
public String getSpatialAggregateSQL(String columnName, int aggregation) {
final StringBuffer aggregateFunction = new StringBuffer();
final SpatialAggregate sa = new SpatialAggregate( aggregation );
if ( sa.getAggregateSyntax() == null ) {
throw new IllegalArgumentException(
"Unknown Spatial Aggregation ("
+ aggregation + ")."
);
}
aggregateFunction.append( sa.getAggregateSyntax() );
aggregateFunction.append( "(" );
if ( sa.isAggregateType() ) {
aggregateFunction.append( "SDOAGGRTYPE(" );
}
aggregateFunction.append( columnName );
// TODO tolerance must by configurable
if ( sa.isAggregateType() ) {
aggregateFunction.append( ", " ).append( .001 ).append( ")" );
}
aggregateFunction.append( ")" );
return aggregateFunction.toString();
}
/**
* Returns The SQL fragment when parsing a <code>DWithinExpression</code>.
*
* @param columnName The geometry column to test against
*
* @return The SQL fragment when parsing a <code>DWithinExpression</code>.
*/
@Override
public String getDWithinSQL(String columnName) {
return "SDO_WITHIN_DISTANCE (" + columnName + ",?, ?) = 'TRUE' ";
}
/**
* Returns the SQL fragment when parsing an <code>HavingSridExpression</code>.
*
* @param columnName The geometry column to test against
*
* @return The SQL fragment for an <code>HavingSridExpression</code>.
*/
@Override
public String getHavingSridSQL(String columnName) {
return String.format( " (MDSYS.ST_GEOMETRY(%s).ST_SRID() = ?)", columnName );
}
/**
* Returns the SQL fragment when parsing a <code>IsEmptyExpression</code> or
* <code>IsNotEmpty</code> expression.
*
* @param columnName The geometry column
* @param isEmpty Whether the geometry is tested for empty or non-empty
*
* @return The SQL fragment for the isempty function
*/
@Override
public String getIsEmptySQL(String columnName, boolean isEmpty) {
return String.format( "( MDSYS.ST_GEOMETRY(%s).ST_ISEMPTY() = %d )", columnName, isEmpty ? 1 : 0 );
}
/**
* Returns true if this <code>SpatialDialect</code> supports a specific filtering function.
* <p> This is intended to signal DB-support for fast window queries, or MBR-overlap queries.</p>
*
* @return True if filtering is supported
*/
@Override
public boolean supportsFiltering() {
return true;
}
/**
* Does this dialect supports the specified <code>SpatialFunction</code>.
*
* @param function <code>SpatialFunction</code>
*
* @return True if this <code>SpatialDialect</code> supports the spatial function specified by the function parameter.
*/
@Override
public boolean supports(SpatialFunction function) {
return false;
}
}

View File

@ -9,33 +9,25 @@
import java.io.Serializable;
import java.sql.Types;
import java.util.List;
import java.util.Map;
import org.geolatte.geom.codec.db.oracle.ConnectionFinder;
import org.geolatte.geom.codec.db.oracle.OracleJDBCTypeFactory;
import org.jboss.logging.Logger;
import org.hibernate.QueryException;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.dialect.Oracle10gDialect;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.HibernateSpatialConfigurationSettings;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.SpatialAnalysis;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.SpatialRelation;
import org.hibernate.spatial.dialect.oracle.criterion.OracleSpatialAggregate;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
/**
* Spatial Dialect for Oracle10g databases.
@ -44,107 +36,26 @@
*/
public class OracleSpatial10gDialect extends Oracle10gDialect implements SpatialDialect, Serializable {
private final boolean isOgcStrict;
private static final HSMessageLogger log = Logger.getMessageLogger(
HSMessageLogger.class,
OracleSpatial10gDialect.class.getName()
);
transient private OracleSDOSupport sdoSupport = new OracleSDOSupport( true );
/**
* Constructs the dialect with the specified configuration
*
* Constructs the dialect with
*/
public OracleSpatial10gDialect() {
super();
this.isOgcStrict = true;
// register geometry type
registerColumnType( Types.STRUCT, "MDSYS.SDO_GEOMETRY" );
for ( Map.Entry<String, SQLFunction> entry : sdoSupport.functionsToRegister() ) {
registerFunction( entry.getKey(), entry.getValue() );
}
// registering OGC functions
// (spec_simplefeatures_sql_99-04.pdf)
// section 2.1.1.1
registerFunction( "dimension", new GetDimensionFunction() );
registerFunction( "geometrytype", new GetGeometryTypeFunction() );
registerFunction( "srid", new SDOObjectProperty( "SDO_SRID", StandardBasicTypes.INTEGER ) );
registerFunction( "envelope", new StandardSQLFunction( "SDO_GEOM.SDO_MBR" ) );
registerFunction( "astext", new AsTextFunction() );
registerFunction( "asbinary", new StandardSQLFunction( "SDO_UTIL.TO_WKBGEOMETRY", StandardBasicTypes.BINARY ) );
registerFunction(
"isempty",
new WrappedOGCFunction( "OGC_ISEMPTY", StandardBasicTypes.BOOLEAN, new boolean[] {true} )
);
registerFunction(
"issimple",
new WrappedOGCFunction( "OGC_ISSIMPLE", StandardBasicTypes.BOOLEAN, new boolean[] {true} )
);
registerFunction( "boundary", new WrappedOGCFunction( "OGC_BOUNDARY", new boolean[] {true} ) );
// registerFunction("area", new AreaFunction());
// Register functions for spatial relation constructs
// section 2.1.1.2
registerFunction( "overlaps", new SpatialRelateFunction( "overlaps", SpatialRelation.OVERLAPS ) );
registerFunction( "intersects", new SpatialRelateFunction( "intersects", SpatialRelation.INTERSECTS ) );
registerFunction( "contains", new SpatialRelateFunction( "contains", SpatialRelation.CONTAINS ) );
registerFunction( "crosses", new SpatialRelateFunction( "crosses", SpatialRelation.CROSSES ) );
registerFunction( "disjoint", new SpatialRelateFunction( "disjoint", SpatialRelation.DISJOINT ) );
registerFunction( "equals", new SpatialRelateFunction( "equals", SpatialRelation.EQUALS ) );
registerFunction( "touches", new SpatialRelateFunction( "touches", SpatialRelation.TOUCHES ) );
registerFunction( "within", new SpatialRelateFunction( "within", SpatialRelation.WITHIN ) );
registerFunction(
"relate",
new WrappedOGCFunction( "OGC_RELATE", StandardBasicTypes.BOOLEAN, new boolean[] {true, true, false} )
);
// Register spatial analysis functions.
// Section 2.1.1.3
registerFunction(
"distance",
new SpatialAnalysisFunction( "distance", StandardBasicTypes.DOUBLE, SpatialAnalysis.DISTANCE )
);
registerFunction( "buffer", new SpatialAnalysisFunction( "buffer", SpatialAnalysis.BUFFER ) );
registerFunction( "convexhull", new SpatialAnalysisFunction( "convexhull", SpatialAnalysis.CONVEXHULL ) );
registerFunction( "difference", new SpatialAnalysisFunction( "difference", SpatialAnalysis.DIFFERENCE ) );
registerFunction( "intersection", new SpatialAnalysisFunction( "intersection", SpatialAnalysis.INTERSECTION ) );
registerFunction(
"symdifference",
new SpatialAnalysisFunction( "symdifference", SpatialAnalysis.SYMDIFFERENCE )
);
registerFunction( "geomunion", new SpatialAnalysisFunction( "union", SpatialAnalysis.UNION ) );
// we rename OGC union to geomunion because union is a reserved SQL
// keyword. (See also postgis documentation).
// portable spatial aggregate functions
registerFunction( "extent", new SpatialAggregationFunction( "extent", false, OracleSpatialAggregate.EXTENT ) );
//other common functions
registerFunction( "transform", new StandardSQLFunction( "SDO_CS.TRANSFORM" ) );
// Oracle specific Aggregate functions
registerFunction(
"centroid",
new SpatialAggregationFunction( "extent", false, OracleSpatialAggregate.CENTROID )
);
registerFunction(
"concat_lines",
new SpatialAggregationFunction( "extent", false, OracleSpatialAggregate.CONCAT_LINES )
);
registerFunction(
"aggr_convexhull",
new SpatialAggregationFunction( "extent", false, OracleSpatialAggregate.CONVEXHULL )
);
registerFunction(
"aggr_union",
new SpatialAggregationFunction( "extent", false, OracleSpatialAggregate.UNION )
);
registerFunction(
"lrs_concat",
new SpatialAggregationFunction( "lrsconcat", false, OracleSpatialAggregate.LRS_CONCAT )
);
}
@Override
@ -153,282 +64,44 @@ public void contributeTypes(TypeContributions typeContributions, ServiceRegistry
typeContributions,
serviceRegistry
);
final ConfigurationService cfgService = serviceRegistry.getService( ConfigurationService.class );
final StrategySelector strategySelector = serviceRegistry.getService( StrategySelector.class );
final ConnectionFinder connectionFinder = strategySelector.resolveStrategy(
ConnectionFinder.class,
cfgService.getSetting( HibernateSpatialConfigurationSettings.CONNECTION_FINDER, String.class, "org.geolatte.geom.codec.db.oracle.DefaultConnectionFinder" )
);
log.connectionFinder( connectionFinder.getClass().getCanonicalName() );
final SDOGeometryTypeDescriptor sdoGeometryTypeDescriptor = new SDOGeometryTypeDescriptor(
new OracleJDBCTypeFactory(
connectionFinder
)
);
typeContributions.contributeType( new GeolatteGeometryType( sdoGeometryTypeDescriptor ) );
typeContributions.contributeType( new JTSGeometryType( sdoGeometryTypeDescriptor ) );
sdoSupport.contributeTypes( typeContributions, serviceRegistry );
}
String getNativeSpatialRelateSQL(String arg1, String arg2, int spatialRelation) {
String mask = "";
boolean negate = false;
switch ( spatialRelation ) {
case SpatialRelation.INTERSECTS:
mask = "ANYINTERACT";
break;
case SpatialRelation.CONTAINS:
mask = "CONTAINS+COVERS";
break;
case SpatialRelation.CROSSES:
throw new UnsupportedOperationException(
"Oracle Spatial does't have equivalent CROSSES relationship"
);
case SpatialRelation.DISJOINT:
mask = "ANYINTERACT";
negate = true;
break;
case SpatialRelation.EQUALS:
mask = "EQUAL";
break;
case SpatialRelation.OVERLAPS:
mask = "OVERLAPBDYDISJOINT+OVERLAPBDYINTERSECT";
break;
case SpatialRelation.TOUCHES:
mask = "TOUCH";
break;
case SpatialRelation.WITHIN:
mask = "INSIDE+COVEREDBY";
break;
default:
throw new IllegalArgumentException(
"undefined SpatialRelation passed (" + spatialRelation
+ ")"
);
}
final StringBuffer buffer = new StringBuffer( "CASE SDO_RELATE(" ).append( arg1 )
.append( "," )
.append( arg2 )
.append( ",'mask=" + mask + "') " );
if ( !negate ) {
buffer.append( " WHEN 'TRUE' THEN 1 ELSE 0 END" );
}
else {
buffer.append( " WHEN 'TRUE' THEN 0 ELSE 1 END" );
}
return buffer.toString();
}
String getOGCSpatialRelateSQL(String arg1, String arg2, int spatialRelation) {
final StringBuffer ogcFunction = new StringBuffer( "MDSYS." );
switch ( spatialRelation ) {
case SpatialRelation.INTERSECTS:
ogcFunction.append( "OGC_INTERSECTS" );
break;
case SpatialRelation.CONTAINS:
ogcFunction.append( "OGC_CONTAINS" );
break;
case SpatialRelation.CROSSES:
ogcFunction.append( "OGC_CROSS" );
break;
case SpatialRelation.DISJOINT:
ogcFunction.append( "OGC_DISJOINT" );
break;
case SpatialRelation.EQUALS:
ogcFunction.append( "OGC_EQUALS" );
break;
case SpatialRelation.OVERLAPS:
ogcFunction.append( "OGC_OVERLAP" );
break;
case SpatialRelation.TOUCHES:
ogcFunction.append( "OGC_TOUCH" );
break;
case SpatialRelation.WITHIN:
ogcFunction.append( "OGC_WITHIN" );
break;
default:
throw new IllegalArgumentException(
"Unknown SpatialRelation ("
+ spatialRelation + ")."
);
}
ogcFunction.append( "(" ).append( "MDSYS.ST_GEOMETRY.FROM_SDO_GEOM(" )
.append( arg1 ).append( ")," ).append(
"MDSYS.ST_GEOMETRY.FROM_SDO_GEOM("
).append( arg2 )
.append( ")" ).append( ")" );
return ogcFunction.toString();
}
String getNativeSpatialAggregateSQL(String arg1, int aggregation) {
final StringBuffer aggregateFunction = new StringBuffer();
final SpatialAggregate sa = new SpatialAggregate( aggregation );
if ( sa.getAggregateSyntax() == null ) {
throw new IllegalArgumentException(
"Unknown Spatial Aggregation ("
+ aggregation + ")."
);
}
aggregateFunction.append( sa.getAggregateSyntax() );
aggregateFunction.append( "(" );
if ( sa.isAggregateType() ) {
aggregateFunction.append( "SDOAGGRTYPE(" );
}
aggregateFunction.append( arg1 );
// TODO tolerance must by configurable
if ( sa.isAggregateType() ) {
aggregateFunction.append( ", " ).append( .001 ).append( ")" );
}
aggregateFunction.append( ")" );
return aggregateFunction.toString();
}
private StringBuffer wrapInSTGeometry(String geomColumn, StringBuffer toAdd) {
return toAdd.append( "MDSYS.ST_GEOMETRY(" ).append( geomColumn )
.append( ")" );
}
@Override
public String getSpatialFilterExpression(String columnName) {
final StringBuffer buffer = new StringBuffer( "SDO_FILTER(" );
buffer.append( columnName );
buffer.append( ",?) = 'TRUE' " );
return buffer.toString();
return sdoSupport.getSpatialFilterExpression( columnName );
}
@Override
public String getSpatialRelateSQL(String columnName, int spatialRelation) {
String sql = (isOGCStrict() ?
getOGCSpatialRelateSQL( columnName, "?", spatialRelation ) :
getNativeSpatialRelateSQL( columnName, "?", spatialRelation )) + " = 1";
sql += " and " + columnName + " is not null";
return sql;
}
String getSpatialAnalysisSQL(List args, int spatialAnalysisFunction, boolean useFilter) {
return isOGCStrict() ? getOGCSpatialAnalysisSQL( args, spatialAnalysisFunction ) : getNativeSpatialAnalysisSQL(
args,
spatialAnalysisFunction
);
return sdoSupport.getSpatialRelateSQL( columnName, spatialRelation );
}
@Override
public String getSpatialAggregateSQL(String columnName, int spatialAggregateFunction) {
return getNativeSpatialAggregateSQL( columnName, spatialAggregateFunction );
public String getSpatialAggregateSQL(String columnName, int aggregation) {
return sdoSupport.getSpatialAggregateSQL( columnName, aggregation );
}
@Override
public String getDWithinSQL(String columnName) {
return "SDO_WITHIN_DISTANCE (" + columnName + ",?, ?) = 'TRUE' ";
return sdoSupport.getDWithinSQL( columnName );
}
@Override
public String getHavingSridSQL(String columnName) {
return String.format( " (MDSYS.ST_GEOMETRY(%s).ST_SRID() = ?)", columnName );
return sdoSupport.getHavingSridSQL( columnName );
}
@Override
public String getIsEmptySQL(String columnName, boolean isEmpty) {
return String.format( "( MDSYS.ST_GEOMETRY(%s).ST_ISEMPTY() = %d )", columnName, isEmpty ? 1 : 0 );
return sdoSupport.getIsEmptySQL( columnName, isEmpty );
}
private String getOGCSpatialAnalysisSQL(List args, int spatialAnalysisFunction) {
boolean[] geomArgs;
final StringBuffer ogcFunction = new StringBuffer( "MDSYS." );
boolean isGeomReturn = true;
switch ( spatialAnalysisFunction ) {
case SpatialAnalysis.BUFFER:
ogcFunction.append( "OGC_BUFFER" );
geomArgs = new boolean[] {true, false};
break;
case SpatialAnalysis.CONVEXHULL:
ogcFunction.append( "OGC_CONVEXHULL" );
geomArgs = new boolean[] {true};
break;
case SpatialAnalysis.DIFFERENCE:
ogcFunction.append( "OGC_DIFFERENCE" );
geomArgs = new boolean[] {true, true};
break;
case SpatialAnalysis.DISTANCE:
ogcFunction.append( "OGC_DISTANCE" );
geomArgs = new boolean[] {true, true};
isGeomReturn = false;
break;
case SpatialAnalysis.INTERSECTION:
ogcFunction.append( "OGC_INTERSECTION" );
geomArgs = new boolean[] {true, true};
break;
case SpatialAnalysis.SYMDIFFERENCE:
ogcFunction.append( "OGC_SYMMETRICDIFFERENCE" );
geomArgs = new boolean[] {true, true};
break;
case SpatialAnalysis.UNION:
ogcFunction.append( "OGC_UNION" );
geomArgs = new boolean[] {true, true};
break;
default:
throw new IllegalArgumentException(
"Unknown SpatialAnalysisFunction ("
+ spatialAnalysisFunction + ")."
);
}
if ( args.size() < geomArgs.length ) {
throw new QueryException(
"Insufficient arguments for spatial analysis function (function type: "
+ spatialAnalysisFunction + ")."
);
}
ogcFunction.append( "(" );
for ( int i = 0; i < geomArgs.length; i++ ) {
if ( i > 0 ) {
ogcFunction.append( "," );
}
if ( geomArgs[i] ) {
wrapInSTGeometry( (String) args.get( i ), ogcFunction );
}
else {
ogcFunction.append( args.get( i ) );
}
}
ogcFunction.append( ")" );
if ( isGeomReturn ) {
ogcFunction.append( ".geom" );
}
return ogcFunction.toString();
}
private String getNativeSpatialAnalysisSQL(List args, int spatialAnalysis) {
return getOGCSpatialAnalysisSQL( args, spatialAnalysis );
}
/**
* Reports whether this dialect is in OGC_STRICT mode or not.
* <p/>
* This method is for testing purposes.
*
* @return true if in OGC_STRICT mode, false otherwise
*/
public boolean isOGCStrict() {
return isOgcStrict;
}
@Override
public boolean supportsFiltering() {
return true;
return sdoSupport.supportsFiltering();
}
@Override
@ -436,97 +109,5 @@ public boolean supports(SpatialFunction function) {
return (getFunctions().get( function.toString() ) != null);
}
/**
* Implementation of the OGC astext function for HQL.
*/
private static class AsTextFunction extends StandardSQLFunction {
private AsTextFunction() {
super( "astext", StandardBasicTypes.STRING );
}
public String render(Type firstArgumentType, final List args, final SessionFactoryImplementor factory) {
final StringBuffer buf = new StringBuffer();
if ( args.isEmpty() ) {
throw new IllegalArgumentException( "First Argument in arglist must be object " + "to which method is applied" );
}
buf.append( "TO_CHAR(SDO_UTIL.TO_WKTGEOMETRY(" ).append( args.get( 0 ) ).append( "))" );
return buf.toString();
}
}
/**
* HQL Spatial relation function.
*/
private class SpatialRelateFunction extends StandardSQLFunction {
private final int relation;
private SpatialRelateFunction(final String name, final int relation) {
super(
name, isOGCStrict() ? StandardBasicTypes.BOOLEAN
: new SDOBooleanType()
);
this.relation = relation;
}
public String render(Type firstArgumentType, final List args, final SessionFactoryImplementor factory) {
if ( args.size() < 2 ) {
throw new QueryException(
"Spatial relate functions require at least two arguments"
);
}
return isOGCStrict() ?
getOGCSpatialRelateSQL(
(String) args.get( 0 ),
(String) args.get( 1 ), this.relation
) :
getNativeSpatialRelateSQL(
(String) args.get( 0 ),
(String) args.get( 1 ), this.relation
);
}
}
private class SpatialAnalysisFunction extends StandardSQLFunction {
private final int analysis;
private SpatialAnalysisFunction(String name, Type returnType, int analysis) {
super( name, returnType );
this.analysis = analysis;
}
private SpatialAnalysisFunction(String name, int analysis) {
this( name, null, analysis );
}
public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) {
return isOGCStrict() ? getSpatialAnalysisSQL(
args, this.analysis,
false
) : getNativeSpatialAnalysisSQL( args, analysis );
}
}
private class SpatialAggregationFunction extends StandardSQLFunction {
private final int aggregation;
private SpatialAggregationFunction(String name, boolean isProjection, int aggregation) {
super( name );
this.aggregation = aggregation;
}
public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) {
return getNativeSpatialAggregateSQL(
(String) args.get( 0 ),
this.aggregation
);
}
}
}

View File

@ -0,0 +1,351 @@
/*
* 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 java.util.List;
import org.hibernate.QueryException;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.spatial.SpatialAnalysis;
import org.hibernate.spatial.SpatialRelation;
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
import org.hibernate.spatial.dialect.oracle.criterion.OracleSpatialAggregate;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
/**
* Helper class to register functions in the Oracle Spatial Dialects
* Created by Karel Maesen, Geovise BVBA on 02/03/16.
*/
class OracleSpatialFunctions extends SpatialFunctionsRegistry {
OracleSpatialFunctions(boolean strictOgc, OracleSDOSupport sdoSupport) {
put( "dimension", new GetDimensionFunction() );
put( "geometrytype", new GetGeometryTypeFunction() );
put( "srid", new SDOObjectProperty( "SDO_SRID", StandardBasicTypes.INTEGER ) );
put( "envelope", new StandardSQLFunction( "SDO_GEOM.SDO_MBR" ) );
put( "astext", new AsTextFunction() );
put(
"asbinary",
new StandardSQLFunction( "SDO_UTIL.TO_WKBGEOMETRY", StandardBasicTypes.BINARY )
);
put(
"isempty",
new WrappedOGCFunction( "OGC_ISEMPTY", StandardBasicTypes.BOOLEAN, new boolean[] {true} )
);
put(
"issimple",
new WrappedOGCFunction( "OGC_ISSIMPLE", StandardBasicTypes.BOOLEAN, new boolean[] {true} )
);
put( "boundary", new WrappedOGCFunction( "OGC_BOUNDARY", new boolean[] {true} ) );
// put("area", new AreaFunction());
// Register functions for spatial relation constructs
// section 2.1.1.2
put(
"overlaps",
new SpatialRelateFunction( "overlaps", SpatialRelation.OVERLAPS, strictOgc, sdoSupport )
);
put(
"intersects",
new SpatialRelateFunction( "intersects", SpatialRelation.INTERSECTS, strictOgc, sdoSupport )
);
put(
"contains",
new SpatialRelateFunction( "contains", SpatialRelation.CONTAINS, strictOgc, sdoSupport )
);
put(
"crosses",
new SpatialRelateFunction( "crosses", SpatialRelation.CROSSES, strictOgc, sdoSupport )
);
put(
"disjoint",
new SpatialRelateFunction( "disjoint", SpatialRelation.DISJOINT, strictOgc, sdoSupport )
);
put(
"equals",
new SpatialRelateFunction( "equals", SpatialRelation.EQUALS, strictOgc, sdoSupport )
);
put(
"touches",
new SpatialRelateFunction( "touches", SpatialRelation.TOUCHES, strictOgc, sdoSupport )
);
put(
"within",
new SpatialRelateFunction( "within", SpatialRelation.WITHIN, strictOgc, sdoSupport )
);
put(
"relate",
new WrappedOGCFunction( "OGC_RELATE", StandardBasicTypes.BOOLEAN, new boolean[] {true, true, false} )
);
// Register spatial analysis functions.
// Section 2.1.1.3
put(
"distance",
new SpatialAnalysisFunction(
"distance",
StandardBasicTypes.DOUBLE,
SpatialAnalysis.DISTANCE,
strictOgc
)
);
put(
"buffer",
new SpatialAnalysisFunction( "buffer", SpatialAnalysis.BUFFER, strictOgc )
);
put(
"convexhull",
new SpatialAnalysisFunction( "convexhull", SpatialAnalysis.CONVEXHULL, strictOgc )
);
put(
"difference",
new SpatialAnalysisFunction( "difference", SpatialAnalysis.DIFFERENCE, strictOgc )
);
put(
"intersection",
new SpatialAnalysisFunction(
"intersection",
SpatialAnalysis.INTERSECTION,
strictOgc
)
);
put(
"symdifference",
new SpatialAnalysisFunction(
"symdifference",
SpatialAnalysis.SYMDIFFERENCE,
strictOgc
)
);
put(
"geomunion",
new SpatialAnalysisFunction( "union", SpatialAnalysis.UNION, strictOgc )
);
// we rename OGC union to geomunion because union is a reserved SQL
// keyword. (See also postgis documentation).
// portable spatial aggregate functions
put(
"extent",
new SpatialAggregationFunction( "extent", OracleSpatialAggregate.EXTENT, sdoSupport )
);
//other common functions
put( "transform", new StandardSQLFunction( "SDO_CS.TRANSFORM" ) );
// Oracle specific Aggregate functions
put(
"centroid",
new SpatialAggregationFunction( "extent", OracleSpatialAggregate.CENTROID, sdoSupport )
);
put(
"concat_lines",
new SpatialAggregationFunction( "extent", OracleSpatialAggregate.CONCAT_LINES, sdoSupport )
);
put(
"aggr_convexhull",
new SpatialAggregationFunction( "extent", OracleSpatialAggregate.CONVEXHULL, sdoSupport )
);
put(
"aggr_union",
new SpatialAggregationFunction( "extent", OracleSpatialAggregate.UNION, sdoSupport )
);
put(
"lrs_concat",
new SpatialAggregationFunction( "lrsconcat", OracleSpatialAggregate.LRS_CONCAT, sdoSupport )
);
}
/**
* Implementation of the OGC astext function for HQL.
*/
private static class AsTextFunction extends StandardSQLFunction {
private AsTextFunction() {
super( "astext", StandardBasicTypes.STRING );
}
public String render(Type firstArgumentType, final List args, final SessionFactoryImplementor factory) {
final StringBuilder buf = new StringBuilder();
if ( args.isEmpty() ) {
throw new IllegalArgumentException( "First Argument in arglist must be object " + "to which method is applied" );
}
buf.append( "TO_CHAR(SDO_UTIL.TO_WKTGEOMETRY(" ).append( args.get( 0 ) ).append( "))" );
return buf.toString();
}
}
static String getOGCSpatialAnalysisSQL(List args, int spatialAnalysisFunction) {
boolean[] geomArgs;
final StringBuffer ogcFunction = new StringBuffer( "MDSYS." );
boolean isGeomReturn = true;
switch ( spatialAnalysisFunction ) {
case SpatialAnalysis.BUFFER:
ogcFunction.append( "OGC_BUFFER" );
geomArgs = new boolean[] {true, false};
break;
case SpatialAnalysis.CONVEXHULL:
ogcFunction.append( "OGC_CONVEXHULL" );
geomArgs = new boolean[] {true};
break;
case SpatialAnalysis.DIFFERENCE:
ogcFunction.append( "OGC_DIFFERENCE" );
geomArgs = new boolean[] {true, true};
break;
case SpatialAnalysis.DISTANCE:
ogcFunction.append( "OGC_DISTANCE" );
geomArgs = new boolean[] {true, true};
isGeomReturn = false;
break;
case SpatialAnalysis.INTERSECTION:
ogcFunction.append( "OGC_INTERSECTION" );
geomArgs = new boolean[] {true, true};
break;
case SpatialAnalysis.SYMDIFFERENCE:
ogcFunction.append( "OGC_SYMMETRICDIFFERENCE" );
geomArgs = new boolean[] {true, true};
break;
case SpatialAnalysis.UNION:
ogcFunction.append( "OGC_UNION" );
geomArgs = new boolean[] {true, true};
break;
default:
throw new IllegalArgumentException(
"Unknown SpatialAnalysisFunction ("
+ spatialAnalysisFunction + ")."
);
}
if ( args.size() < geomArgs.length ) {
throw new QueryException(
"Insufficient arguments for spatial analysis function (function type: "
+ spatialAnalysisFunction + ")."
);
}
ogcFunction.append( "(" );
for ( int i = 0; i < geomArgs.length; i++ ) {
if ( i > 0 ) {
ogcFunction.append( "," );
}
if ( geomArgs[i] ) {
wrapInSTGeometry( (String) args.get( i ), ogcFunction );
}
else {
ogcFunction.append( args.get( i ) );
}
}
ogcFunction.append( ")" );
if ( isGeomReturn ) {
ogcFunction.append( ".geom" );
}
return ogcFunction.toString();
}
private static StringBuffer wrapInSTGeometry(String geomColumn, StringBuffer toAdd) {
return toAdd.append( "MDSYS.ST_GEOMETRY(" ).append( geomColumn )
.append( ")" );
}
static String getNativeSpatialAnalysisSQL(List args, int spatialAnalysis) {
return getOGCSpatialAnalysisSQL( args, spatialAnalysis );
}
static String getSpatialAnalysisSQL(List args, int spatialAnalysisFunction) {
return getOGCSpatialAnalysisSQL( args, spatialAnalysisFunction );
}
/**
* HQL Spatial relation function.
*/
private static class SpatialRelateFunction extends StandardSQLFunction {
private final int relation;
private final boolean isOGCStrict;
private OracleSDOSupport sdo;
private SpatialRelateFunction(
final String name,
final int relation,
final boolean isOGCStrict,
OracleSDOSupport sdo) {
super( name, StandardBasicTypes.BOOLEAN );
this.relation = relation;
this.isOGCStrict = isOGCStrict;
this.sdo = sdo;
}
public String render(Type firstArgumentType, final List args, final SessionFactoryImplementor factory) {
if ( args.size() < 2 ) {
throw new QueryException(
"Spatial relate functions require at least two arguments"
);
}
return isOGCStrict ?
sdo.getOGCSpatialRelateSQL(
(String) args.get( 0 ),
(String) args.get( 1 ), this.relation
) :
sdo.getNativeSpatialRelateSQL(
(String) args.get( 0 ),
(String) args.get( 1 ), this.relation
);
}
}
private static class SpatialAnalysisFunction extends StandardSQLFunction {
private final int analysis;
private final boolean isOGCStrict;
private SpatialAnalysisFunction(String name, Type returnType, int analysis, boolean isOGCStrict) {
super( name, returnType );
this.analysis = analysis;
this.isOGCStrict = isOGCStrict;
}
private SpatialAnalysisFunction(String name, int analysis, boolean isOGCStrict) {
this( name, null, analysis, isOGCStrict );
}
public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) {
return isOGCStrict ? getSpatialAnalysisSQL( args, this.analysis ) : getNativeSpatialAnalysisSQL(
args,
analysis
);
}
}
static class SpatialAggregationFunction extends StandardSQLFunction {
private final int aggregation;
private final OracleSDOSupport sdo;
private SpatialAggregationFunction(String name, int aggregation, OracleSDOSupport dialect) {
super( name );
this.aggregation = aggregation;
this.sdo = dialect;
}
public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) {
return sdo.getSpatialAggregateSQL(
(String) args.get( 0 ),
this.aggregation
);
}
}
}

View File

@ -0,0 +1,104 @@
/*
* 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 java.io.Serializable;
import java.sql.Types;
import java.util.Map;
import org.jboss.logging.Logger;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.Oracle10gDialect;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
/**
* A Spatial Dialect for Oracle 10g/11g that uses the "native" SDO spatial operators.
* <p>
* Created by Karel Maesen, Geovise BVBA on 11/02/17.
*/
public class OracleSpatialSDO10gDialect extends Oracle10gDialect implements SpatialDialect, Serializable {
private static final HSMessageLogger log = Logger.getMessageLogger(
HSMessageLogger.class,
OracleSpatial10gDialect.class.getName()
);
transient private OracleSDOSupport sdoSupport = new OracleSDOSupport( false );
/**
* Constructs the dialect
*/
public OracleSpatialSDO10gDialect() {
super();
// register geometry type
registerColumnType( Types.STRUCT, "MDSYS.SDO_GEOMETRY" );
for ( Map.Entry<String, SQLFunction> entry : sdoSupport.functionsToRegister() ) {
registerFunction( entry.getKey(), entry.getValue() );
}
}
@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes(
typeContributions,
serviceRegistry
);
sdoSupport.contributeTypes( typeContributions, serviceRegistry );
}
@Override
public String getSpatialFilterExpression(String columnName) {
return sdoSupport.getSpatialFilterExpression( columnName );
}
@Override
public String getSpatialRelateSQL(String columnName, int spatialRelation) {
return sdoSupport.getSDOSpatialRelateSQL( columnName, spatialRelation );
}
@Override
public String getSpatialAggregateSQL(String columnName, int aggregation) {
return sdoSupport.getSpatialAggregateSQL( columnName, aggregation );
}
@Override
public String getDWithinSQL(String columnName) {
return sdoSupport.getDWithinSQL( columnName );
}
@Override
public String getHavingSridSQL(String columnName) {
return sdoSupport.getHavingSridSQL( columnName );
}
@Override
public String getIsEmptySQL(String columnName, boolean isEmpty) {
return sdoSupport.getIsEmptySQL( columnName, isEmpty );
}
@Override
public boolean supportsFiltering() {
return sdoSupport.supportsFiltering();
}
@Override
public boolean supports(SpatialFunction function) {
return !function.equals( SpatialFunction.crosses ) && (getFunctions().get( function.toString() ) != null);
}
}

View File

@ -46,5 +46,4 @@ public SpatialService(StandardServiceRegistryBuilder serviceRegistryBuilder) {
public boolean isEnabled() {
return integrationEnabled;
}
}

View File

@ -72,7 +72,8 @@ private static Class<? extends TestSupport> getSupportFactoryClass(Dialect diale
"org.hibernate.spatial.dialect.mysql.MySQL56InnoDBSpatialDialect".equals( canonicalName ) ) {
return MySQL56TestSupport.class;
}
if ( "org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect".equals( canonicalName ) ) {
if ( "org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect".equals( canonicalName ) ||
"org.hibernate.spatial.dialect.oracle.OracleSpatialSDO10gDialect".equals( canonicalName )) {
return OracleSDOTestSupport.class;
}
throw new IllegalArgumentException( "Dialect not known in test suite" );

View File

@ -13,11 +13,11 @@ hibernate.show_sql true
hibernate.max_fetch_depth 5
hibernate.dialect @db.dialect@
hibernate.connection.driver_class @jdbc.driver@
hibernate.connection.url @jdbc.url@
hibernate.connection.username @jdbc.user@
hibernate.connection.password @jdbc.pass@
#hibernate.dialect @db.dialect@
#hibernate.connection.driver_class @jdbc.driver@
#hibernate.connection.url @jdbc.url@
#hibernate.connection.username @jdbc.user@
#hibernate.connection.password @jdbc.pass@
#hibernate.cache.region_prefix hibernate.test
#hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory
@ -47,17 +47,19 @@ hibernate.connection.password @jdbc.pass@
##
## Oracle 11g
##
#hibernate.spatial.connection_finder org.hibernate.spatial.dialect.oracle.TestConnectionFinder
#hibernate.dialect org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect
#hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
#hibernate.connection.url jdbc:oracle:thin:@ec2-54-170-61-24.eu-west-1.compute.amazonaws.com:1521/ORCL
#hibernate.connection.username HBS
#hibernate.connection.password HBS
#hibernate.connection.url jdbc:oracle:thin:@localhost:1521/orcl12c
#hibernate.connection.username C##hibernate
#hibernate.connection.password hibernate
##
## Test Oracle ogc_strict property setting
##
#hibernate.spatial.ogc_strict false
hibernate.dialect org.hibernate.spatial.dialect.oracle.OracleSpatialSDO10gDialect
hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
hibernate.connection.url jdbc:oracle:thin:@localhost:1521/orcl12c
hibernate.connection.username C##hibernate
hibernate.connection.password hibernate
#
##