/*
* 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.TypeContributions;
import org.hibernate.dialect.SQLServer2008Dialect;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.SpatialRelation;
import org.hibernate.type.StandardBasicTypes;
/**
* The <code>SpatialDialect</code> for Microsoft SQL Server (2008).
*
* @author Karel Maesen, Martin Steinwender.
*/
public class SqlServer2008SpatialDialect extends SQLServer2008Dialect implements SpatialDialect {
/**
* The short name for this dialect
*/
public static final String SHORT_NAME = "sqlserver";
/**
* Constructs an instance
*/
public SqlServer2008SpatialDialect() {
super();
registerColumnType(
SqlServer2008GeometryTypeDescriptor.INSTANCE.getSqlType(),
"GEOMETRY"
);
// registering OGC functions
// (spec_simplefeatures_sql_99-04.pdf)
// section 2.1.1.1
// Registerfunction calls for registering geometry functions:
// first argument is the OGC standard functionname,
// second the Function as it occurs in the spatial dialect
registerFunction( "dimension", new SQLFunctionTemplate( StandardBasicTypes.INTEGER, "?1.STDimension()" ) );
registerFunction( "geometrytype", new SQLFunctionTemplate( StandardBasicTypes.STRING, "?1.STGeometryType()" ) );
registerFunction( "srid", new SQLFunctionTemplate( StandardBasicTypes.INTEGER, "?1.STSrid" ) );
registerFunction( "envelope", new SqlServerMethod( "STEnvelope" ) );
registerFunction( "astext", new SQLFunctionTemplate( StandardBasicTypes.STRING, "?1.STAsText()" ) );
registerFunction( "asbinary", new SQLFunctionTemplate( StandardBasicTypes.BINARY, "?1.STAsBinary()" ) );
registerFunction( "isempty", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STIsEmpty()" ) );
registerFunction( "issimple", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STIsSimple()" ) );
registerFunction( "boundary", new SqlServerMethod( "STBoundary" ) );
// section 2.1.1.2
// Register functions for spatial relation constructs
registerFunction( "contains", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STContains(?2)" ) );
registerFunction( "crosses", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STCrosses(?2)" ) );
registerFunction( "disjoint", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STDisjoint(?2)" ) );
registerFunction( "equals", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STEquals(?2)" ) );
registerFunction( "intersects", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STIntersects(?2)" ) );
registerFunction( "overlaps", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STOverlaps(?2)" ) );
registerFunction( "touches", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STTouches(?2)" ) );
registerFunction( "within", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STWithin(?2)" ) );
registerFunction( "relate", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.STRelate(?2,?3)" ) );
// section 2.1.1.3
// Register spatial analysis functions.
registerFunction( "distance", new SQLFunctionTemplate( StandardBasicTypes.DOUBLE, "?1.STDistance(?2)" ) );
registerFunction( "buffer", new SqlServerMethod( "STBuffer" ) );
registerFunction( "convexhull", new SqlServerMethod( "STConvexHull" ) );
registerFunction( "difference", new SqlServerMethod( "STDifference" ) );
registerFunction( "intersection", new SqlServerMethod( "STIntersection" ) );
registerFunction( "symdifference", new SqlServerMethod( "STSymDifference" ) );
registerFunction( "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
//registerFunction("extent", new SQLFunctionTemplate(geomType, "?1.STExtent()"));
// section 2.1.9.1 methods on surfaces
registerFunction( "area", new SQLFunctionTemplate( StandardBasicTypes.DOUBLE, "?1.STArea()" ) );
registerFunction( "centroid", new SqlServerMethod( "STCentroid" ) );
registerFunction(
"pointonsurface", new SqlServerMethod( "STPointOnSurface" )
);
}
@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes(
typeContributions,
serviceRegistry
);
typeContributions.contributeType( new GeolatteGeometryType( SqlServer2008GeometryTypeDescriptor.INSTANCE ) );
typeContributions.contributeType( new JTSGeometryType( SqlServer2008GeometryTypeDescriptor.INSTANCE ) );
}
@Override
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";
}
@Override
public String getSpatialFilterExpression(String columnName) {
return columnName + ".Filter(?) = 1";
}
@Override
public String getSpatialAggregateSQL(String columnName, int aggregation) {
throw new UnsupportedOperationException( "No spatial aggregate SQL functions." );
}
@Override
public String getDWithinSQL(String columnName) {
throw new UnsupportedOperationException( "SQL Server has no DWithin function." );
}
@Override
public String getHavingSridSQL(String columnName) {
return columnName + ".STSrid = (?)";
}
@Override
public String getIsEmptySQL(String columnName, boolean isEmpty) {
final String base = "(" + columnName + ".STIsEmpty() ";
return isEmpty ? base + " = 1 )" : base + " = 0 )";
}
@Override
public boolean supportsFiltering() {
return true;
}
@Override
public boolean supports(SpatialFunction function) {
return ( getFunctions().get( function.toString() ) != null );
}
}