/** * $Id: PostgisDialect.java 289 2011-02-15 21:34:56Z maesenka $ * * This file is part of Hibernate Spatial, an extension to the * hibernate ORM solution for geographic data. * * Copyright © 2007 Geovise BVBA * Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium * * This work was partially supported by the European Commission, * under the 6th Framework Programme, contract IST-2-004688-STP. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, visit: http://www.hibernatespatial.org/ */ package org.hibernatespatial.postgis; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.type.CustomType; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.Type; import org.hibernate.usertype.UserType; import org.hibernatespatial.SpatialAggregate; import org.hibernatespatial.SpatialDialect; import org.hibernatespatial.SpatialFunction; import org.hibernatespatial.SpatialRelation; /** * Extends the PostgreSQLDialect by also including information on spatial * operators, constructors and processing functions. * * @author Karel Maesen */ public class PostgisDialectNG2 extends PostgreSQLDialect implements SpatialDialect { protected static final Type geometryCustomType = new CustomType(new PGGeometryUserType(), new String[]{"postgis_geometry"}); public PostgisDialectNG2() { super(); registerTypesAndFunctions(); } protected void registerTypesAndFunctions() { registerColumnType(java.sql.Types.STRUCT, "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 name as // it occurs in the spatial dialect registerFunction("dimension", new StandardSQLFunction("st_dimension", StandardBasicTypes.INTEGER)); registerFunction("geometrytype", new StandardSQLFunction( "st_geometrytype", StandardBasicTypes.STRING)); registerFunction("srid", new StandardSQLFunction("st_srid", StandardBasicTypes.INTEGER)); registerFunction("envelope", new StandardSQLFunction("st_envelope", geometryCustomType)); registerFunction("st_astext", new StandardSQLFunction("st_astext", StandardBasicTypes.STRING)); registerFunction("asbinary", new StandardSQLFunction("st_asbinary", StandardBasicTypes.BINARY)); registerFunction("isempty", new StandardSQLFunction("st_isempty", StandardBasicTypes.BOOLEAN)); registerFunction("issimple", new StandardSQLFunction("st_issimple", StandardBasicTypes.BOOLEAN)); registerFunction("boundary", new StandardSQLFunction("st_boundary", geometryCustomType)); // Register functions for spatial relation constructs registerFunction("overlaps", new StandardSQLFunction("st_overlaps", StandardBasicTypes.BOOLEAN)); registerFunction("intersects", new StandardSQLFunction("st_intersects", StandardBasicTypes.BOOLEAN)); registerFunction("equals", new StandardSQLFunction("st_equals", StandardBasicTypes.BOOLEAN)); registerFunction("contains", new StandardSQLFunction("st_contains", StandardBasicTypes.BOOLEAN)); registerFunction("crosses", new StandardSQLFunction("st_crosses", StandardBasicTypes.BOOLEAN)); registerFunction("disjoint", new StandardSQLFunction("st_disjoint", StandardBasicTypes.BOOLEAN)); registerFunction("touches", new StandardSQLFunction("st_touches", StandardBasicTypes.BOOLEAN)); registerFunction("within", new StandardSQLFunction("st_within", StandardBasicTypes.BOOLEAN)); registerFunction("relate", new StandardSQLFunction("st_relate", StandardBasicTypes.BOOLEAN)); // register the spatial analysis functions registerFunction("distance", new StandardSQLFunction("st_distance", StandardBasicTypes.DOUBLE)); registerFunction("buffer", new StandardSQLFunction("st_buffer", geometryCustomType)); registerFunction("convexhull", new StandardSQLFunction("st_convexhull", geometryCustomType)); registerFunction("difference", new StandardSQLFunction("st_difference", geometryCustomType)); registerFunction("intersection", new StandardSQLFunction( "st_intersection", geometryCustomType)); registerFunction("symdifference", new StandardSQLFunction("st_symdifference", geometryCustomType)); registerFunction("geomunion", new StandardSQLFunction("st_union", geometryCustomType)); //register Spatial Aggregate function registerFunction("extent", new StandardSQLFunction("extent", geometryCustomType)); //other common functions registerFunction("dwithin", new StandardSQLFunction("st_dwithin", StandardBasicTypes.BOOLEAN)); registerFunction("transform", new StandardSQLFunction("st_transform", geometryCustomType)); registerFunction("st_distance_sphere", new StandardSQLFunction("st_distance_sphere", StandardBasicTypes.DOUBLE)); registerFunction("st_line_locate_point", new StandardSQLFunction("st_line_locate_point", StandardBasicTypes.DOUBLE)); registerKeyword("&&"); } public String getSpatialRelateSQL(String columnName, int spatialRelation) { switch (spatialRelation) { case SpatialRelation.WITHIN: return " ST_within(" + columnName + ",?)"; case SpatialRelation.CONTAINS: return " ST_contains(" + columnName + ", ?)"; case SpatialRelation.CROSSES: return " ST_crosses(" + columnName + ", ?)"; case SpatialRelation.OVERLAPS: return " ST_overlaps(" + columnName + ", ?)"; case SpatialRelation.DISJOINT: return " ST_disjoint(" + columnName + ", ?)"; case SpatialRelation.INTERSECTS: return " ST_intersects(" + columnName + ", ?)"; case SpatialRelation.TOUCHES: return " ST_touches(" + columnName + ", ?)"; case SpatialRelation.EQUALS: return " ST_equals(" + columnName + ", ?)"; default: throw new IllegalArgumentException( "Spatial relation is not known by this dialect"); } } public String getDWithinSQL(String columnName) { return "ST_DWithin(" + columnName + ",?,?)"; } public String getHavingSridSQL(String columnName) { return "( ST_srid(" + columnName + ") = ?)"; } public String getIsEmptySQL(String columnName, boolean isEmpty) { String emptyExpr = " ST_IsEmpty(" + columnName + ") "; return isEmpty ? emptyExpr : "( NOT " + emptyExpr + ")"; } public String getSpatialFilterExpression(String columnName) { return "(" + columnName + " && ? ) "; } public UserType getGeometryUserType() { return new PGGeometryUserType(); } public String getSpatialAggregateSQL(String columnName, int aggregation) { switch (aggregation) { case SpatialAggregate.EXTENT: StringBuilder stbuf = new StringBuilder(); stbuf.append("extent(").append(columnName).append(")"); return stbuf.toString(); default: throw new IllegalArgumentException("Aggregation of type " + aggregation + " are not supported by this dialect"); } } public String getDbGeometryTypeName() { return "GEOMETRY"; } public boolean isTwoPhaseFiltering() { return true; } public boolean supportsFiltering() { return true; } public boolean supports(SpatialFunction function) { return (getFunctions().get(function.toString()) != null); } }