diff --git a/hibernate-spatial/databases/mysql5/matrix.gradle b/hibernate-spatial/databases/mysql5/matrix.gradle new file mode 100644 index 0000000000..ec110dbc6e --- /dev/null +++ b/hibernate-spatial/databases/mysql5/matrix.gradle @@ -0,0 +1,24 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program 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 distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +jdbcDependency "mysql:mysql-connector-java:5.1.15" diff --git a/hibernate-spatial/databases/mysql5/resources/hibernate.properties b/hibernate-spatial/databases/mysql5/resources/hibernate.properties new file mode 100644 index 0000000000..068408393e --- /dev/null +++ b/hibernate-spatial/databases/mysql5/resources/hibernate.properties @@ -0,0 +1,42 @@ +# +# Hibernate, Relational Persistence for Idiomatic Java +# +# Copyright (c) 2011, Red Hat Inc. or third-party contributors as +# indicated by the @author tags or express copyright attribution +# statements applied by the authors. All third-party contributions are +# distributed under license by Red Hat Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# Lesser General Public License, as published by the Free Software Foundation. +# +# This program 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 distribution; if not, write to: +# Free Software Foundation, Inc. +# 51 Franklin Street, Fifth Floor +# Boston, MA 02110-1301 USA +# + +hibernate.dialect org.hibernate.spatial.dialect.mysql.MySQLSpatialDialect +hibernate.connection.driver_class com.mysql.jdbc.Driver +hibernate.connection.url jdbc:mysql://localhost/testhbs +hibernate.connection.username hibernate +hibernate.connection.password hibernate + + +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 + + diff --git a/hibernate-spatial/databases/mysql5_innodb/matrix.gradle b/hibernate-spatial/databases/mysql5_innodb/matrix.gradle new file mode 100644 index 0000000000..ec110dbc6e --- /dev/null +++ b/hibernate-spatial/databases/mysql5_innodb/matrix.gradle @@ -0,0 +1,24 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program 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 distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +jdbcDependency "mysql:mysql-connector-java:5.1.15" diff --git a/hibernate-spatial/databases/mysql5_innodb/resources/hibernate.properties b/hibernate-spatial/databases/mysql5_innodb/resources/hibernate.properties new file mode 100644 index 0000000000..144fe23813 --- /dev/null +++ b/hibernate-spatial/databases/mysql5_innodb/resources/hibernate.properties @@ -0,0 +1,42 @@ +# +# Hibernate, Relational Persistence for Idiomatic Java +# +# Copyright (c) 2011, Red Hat Inc. or third-party contributors as +# indicated by the @author tags or express copyright attribution +# statements applied by the authors. All third-party contributions are +# distributed under license by Red Hat Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# Lesser General Public License, as published by the Free Software Foundation. +# +# This program 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 distribution; if not, write to: +# Free Software Foundation, Inc. +# 51 Franklin Street, Fifth Floor +# Boston, MA 02110-1301 USA +# + +hibernate.dialect org.hibernate.spatial.dialect.mysql.MySQLSpatialInnoDBDialect +hibernate.connection.driver_class com.mysql.jdbc.Driver +hibernate.connection.url jdbc:mysql://localhost/testhbs +hibernate.connection.username hibernate +hibernate.connection.password hibernate + + +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 + + diff --git a/hibernate-spatial/hibernate-spatial.gradle b/hibernate-spatial/hibernate-spatial.gradle index 588c117314..5828f211bc 100644 --- a/hibernate-spatial/hibernate-spatial.gradle +++ b/hibernate-spatial/hibernate-spatial.gradle @@ -20,6 +20,7 @@ dependencies { testCompile( [group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4']) // testCompile([group: 'com.oracle.jdbc', name:'ojdbc6', version:'11.1.0.7.0']) // testCompile([group: 'com.microsoft', name: 'sqljdbc', version: '2.0']) +// testRuntime("mysql:mysql-connector-java:5.1.15") matrixRuntime( 'jaxen:jaxen:1.1' ) } diff --git a/hibernate-spatial/matrix-test.sh b/hibernate-spatial/matrix-test.sh index 3e0d5ea7f9..dc3ac526d8 100755 --- a/hibernate-spatial/matrix-test.sh +++ b/hibernate-spatial/matrix-test.sh @@ -5,4 +5,4 @@ if [[ -n $@ ]]; then TASK="$@" fi echo "TASK : $TASK" -gradle -Dhibernate-matrix-databases="/home/maesenka/workspaces/github/hibernate-core/hibernate-spatial/databases" -Dhibernate-matrix-ignore='mysql50,mysql51,postgresql82,postgresql83,postgresql84' $TASK +../gradlew -Dhibernate-matrix-databases="/home/maesenka/workspaces/github/hibernate-core/hibernate-spatial/databases" -Dhibernate-matrix-ignore='mysql50,mysql51,postgresql82,postgresql83,postgresql84' $TASK diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/AbstractJTSGeometryValueBinder.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/AbstractJTSGeometryValueBinder.java new file mode 100644 index 0000000000..872e9b908e --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/AbstractJTSGeometryValueBinder.java @@ -0,0 +1,37 @@ +package org.hibernate.spatial.dialect; + +import com.vividsolutions.jts.geom.Geometry; +import org.hibernate.spatial.jts.JTS; +import org.hibernate.spatial.jts.mgeom.MGeometryFactory; +import org.hibernate.type.descriptor.ValueBinder; +import org.hibernate.type.descriptor.WrapperOptions; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Types; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: 1/19/12 + */ +public abstract class AbstractJTSGeometryValueBinder implements ValueBinder { + + @Override + public void bind(PreparedStatement st, Geometry value, int index, WrapperOptions options) throws SQLException { + if ( value == null ) { + st.setNull( index, Types.STRUCT ); + } + else { + Geometry jtsGeom = (Geometry) value; + Object dbGeom = toNative( jtsGeom, st.getConnection() ); + st.setObject( index, dbGeom ); + } + } + + protected MGeometryFactory getGeometryFactory() { + return JTS.getDefaultGeomFactory(); + } + + protected abstract Object toNative(Geometry jtsGeom, Connection connection); +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/AbstractJTSGeometryValueExtractor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/AbstractJTSGeometryValueExtractor.java new file mode 100644 index 0000000000..1a8b965b94 --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/AbstractJTSGeometryValueExtractor.java @@ -0,0 +1,33 @@ +package org.hibernate.spatial.dialect; + +import com.vividsolutions.jts.geom.Geometry; +import org.hibernate.spatial.jts.JTS; +import org.hibernate.spatial.jts.mgeom.MGeometryFactory; +import org.hibernate.type.descriptor.ValueExtractor; +import org.hibernate.type.descriptor.WrapperOptions; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: 1/19/12 + */ +public abstract class AbstractJTSGeometryValueExtractor implements ValueExtractor { + + @Override + public Geometry extract(ResultSet rs, String name, WrapperOptions options) throws SQLException { + Object geomObj = rs.getObject(name); + return toJTS(geomObj); + } + + protected MGeometryFactory getGeometryFactory() { + return JTS.getDefaultGeomFactory(); + } + + //Note: access is public because it is also used in test class. Besides it is + //side-effect free and doesn't use any intermediate state. So public access is safe. + + abstract public Geometry toJTS(Object object); + +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLGeometryTypeDescriptor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLGeometryTypeDescriptor.java new file mode 100644 index 0000000000..3625a7a521 --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLGeometryTypeDescriptor.java @@ -0,0 +1,37 @@ +package org.hibernate.spatial.dialect.mysql; + +import org.hibernate.type.descriptor.ValueBinder; +import org.hibernate.type.descriptor.ValueExtractor; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; + +import java.sql.Types; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: 1/17/12 + */ +public class MySQLGeometryTypeDescriptor implements SqlTypeDescriptor { + + public static final MySQLGeometryTypeDescriptor INSTANCE = new MySQLGeometryTypeDescriptor(); + + @Override + public int getSqlType() { + return Types.ARRAY; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean canBeRemapped() { + return false; + } + + @Override + public ValueBinder getBinder(JavaTypeDescriptor javaTypeDescriptor) { + return (ValueBinder) new MySQLGeometryValueBinder(); + } + + @Override + public ValueExtractor getExtractor(JavaTypeDescriptor javaTypeDescriptor) { + return (ValueExtractor) new MySQLGeometryValueExtractor(); + } +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLGeometryValueBinder.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLGeometryValueBinder.java new file mode 100644 index 0000000000..2b3444d56f --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLGeometryValueBinder.java @@ -0,0 +1,69 @@ +package org.hibernate.spatial.dialect.mysql; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryCollection; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.io.ByteOrderValues; +import com.vividsolutions.jts.io.WKBWriter; +import org.hibernate.spatial.dialect.AbstractJTSGeometryValueBinder; +import org.hibernate.spatial.jts.JTS; + +import java.sql.Connection; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: 1/19/12 + */ +public class MySQLGeometryValueBinder extends AbstractJTSGeometryValueBinder { + + private static final int SRIDLEN = 4; + + @Override + protected Object toNative(Geometry jtsGeom, Connection connection) { + if (jtsGeom.isEmpty()) return null; + jtsGeom = forceGeometryCollection(jtsGeom); + int srid = jtsGeom.getSRID(); + + WKBWriter writer = new WKBWriter(2, + ByteOrderValues.LITTLE_ENDIAN); + byte[] wkb = writer.write(jtsGeom); + + byte[] byteArr = new byte[wkb.length + SRIDLEN]; + byteArr[3] = (byte) ((srid >> 24) & 0xFF); + byteArr[2] = (byte) ((srid >> 16) & 0xFF); + byteArr[1] = (byte) ((srid >> 8) & 0xFF); + byteArr[0] = (byte) (srid & 0xFF); + System.arraycopy(wkb, 0, byteArr, SRIDLEN, wkb.length); + return byteArr; + } + + private Geometry forceGeometryCollection(Geometry jtsGeom) { + if (jtsGeom.isEmpty()) return createEmptyGeometryCollection(jtsGeom); + if (jtsGeom instanceof GeometryCollection) { + GeometryCollection gc = (GeometryCollection) jtsGeom; + Geometry[] components = new Geometry[gc.getNumGeometries()]; + for (int i = 0; i < gc.getNumGeometries(); i++) { + Geometry component = gc.getGeometryN(i); + if (component.isEmpty()) { + components[i] = jtsGeom.getFactory().createGeometryCollection(null); + } else { + components[i] = component; + } + } + Geometry geometryCollection = jtsGeom.getFactory().createGeometryCollection(components); + geometryCollection.setSRID(jtsGeom.getSRID()); + return geometryCollection; + } + return jtsGeom; + } + + private Geometry createEmptyGeometryCollection(Geometry jtsGeom) { + GeometryFactory factory = jtsGeom.getFactory(); + if (factory == null) { + factory = JTS.getDefaultGeomFactory(); + } + Geometry empty = factory.createGeometryCollection(null); + empty.setSRID(jtsGeom.getSRID()); + return empty; + } +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLGeometryValueExtractor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLGeometryValueExtractor.java new file mode 100644 index 0000000000..5043bca1a6 --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLGeometryValueExtractor.java @@ -0,0 +1,45 @@ +package org.hibernate.spatial.dialect.mysql; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.io.WKBReader; +import org.hibernate.spatial.dialect.AbstractJTSGeometryValueExtractor; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: 1/19/12 + */ +public class MySQLGeometryValueExtractor extends AbstractJTSGeometryValueExtractor { + + private static final int SRIDLEN = 4; + + /** + * Converts the native geometry object to a JTS Geometry. + * + * @param object native database geometry object (depends on the JDBC spatial + * extension of the database) + * @return JTS geometry corresponding to geomObj. + */ + public Geometry toJTS(Object object) { + if (object == null) { + return null; + } + byte[] data = (byte[]) object; + byte[] wkb = new byte[data.length - SRIDLEN]; + System.arraycopy(data, SRIDLEN, wkb, 0, wkb.length); + int srid = 0; + // WKB in MySQL Spatial is always little endian. + srid = data[3] << 24 | (data[2] & 0xff) << 16 | (data[1] & 0xff) << 8 + | (data[0] & 0xff); + Geometry geom = null; + try { + WKBReader reader = new WKBReader(); + geom = reader.read(wkb); + } catch (Exception e) { + throw new RuntimeException( + "Couldn't parse incoming MySQL Spatial data."); + } + geom.setSRID(srid); + return geom; + } + +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLSpatialDialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLSpatialDialect.java new file mode 100644 index 0000000000..c2c870f693 --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLSpatialDialect.java @@ -0,0 +1,243 @@ +/** + * $Id: MySQLSpatialDialect.java 298 2011-03-12 15:29:54Z 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.hibernate.spatial.dialect.mysql; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.MySQLDialect; +import org.hibernate.dialect.function.StandardSQLFunction; +import org.hibernate.spatial.*; +import org.hibernate.type.StandardBasicTypes; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Extends the MySQLDialect by also including information on spatial operators, + * constructors and processing functions. + * + * @author Karel Maesen + * @author Boni Gopalan [3/11/2011:Refactored the code to introduce MySQLSpatialInnoDBDialect without much code duplication] + */ +public class MySQLSpatialDialect extends MySQLDialect implements SpatialDialect { + + public MySQLSpatialDialect() { + super(); + Map functionsToRegister = getFunctionsToRegister(); + Map columnTypes = getColumnTypesToRegister(); + if (null != columnTypes) { + Iterator keys = columnTypes.keySet().iterator(); + while (keys.hasNext()) { + String aKey = keys.next(); + registerColumnType(columnTypes.get(aKey), aKey); + } + } + + if (null != functionsToRegister) { + Iterator keys = functionsToRegister.keySet().iterator(); + while (keys.hasNext()) { + String aKey = keys.next(); + registerFunction(aKey, functionsToRegister.get(aKey)); + + } + } + } + + protected Map getColumnTypesToRegister() { + Map columnTypes = new HashMap(); + columnTypes.put("GEOMETRY", java.sql.Types.ARRAY); + return columnTypes; + } + + protected Map getFunctionsToRegister() { + Map functionsToRegister = new HashMap(); + + // 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 + + functionsToRegister.put("dimension", new StandardSQLFunction("dimension", + StandardBasicTypes.INTEGER)); + functionsToRegister.put("geometrytype", new StandardSQLFunction( + "geometrytype", StandardBasicTypes.STRING)); + functionsToRegister.put("srid", new StandardSQLFunction("srid", + StandardBasicTypes.INTEGER)); + functionsToRegister.put("envelope", new StandardSQLFunction("envelope", + GeometryType.INSTANCE)); + functionsToRegister.put("astext", new StandardSQLFunction("astext", + StandardBasicTypes.STRING)); + functionsToRegister.put("asbinary", new StandardSQLFunction("asbinary", + StandardBasicTypes.BINARY)); + functionsToRegister.put("isempty", new StandardSQLFunction("isempty", + StandardBasicTypes.BOOLEAN)); + functionsToRegister.put("issimple", new StandardSQLFunction("issimple", + StandardBasicTypes.BOOLEAN)); + functionsToRegister.put("boundary", new StandardSQLFunction("boundary", + GeometryType.INSTANCE)); + + // Register functions for spatial relation constructs + functionsToRegister.put("overlaps", new StandardSQLFunction("overlaps", + StandardBasicTypes.BOOLEAN)); + functionsToRegister.put("intersects", new StandardSQLFunction("intersects", + StandardBasicTypes.BOOLEAN)); + functionsToRegister.put("equals", new StandardSQLFunction("equals", + StandardBasicTypes.BOOLEAN)); + functionsToRegister.put("contains", new StandardSQLFunction("contains", + StandardBasicTypes.BOOLEAN)); + functionsToRegister.put("crosses", new StandardSQLFunction("crosses", + StandardBasicTypes.BOOLEAN)); + functionsToRegister.put("disjoint", new StandardSQLFunction("disjoint", + StandardBasicTypes.BOOLEAN)); + functionsToRegister.put("touches", new StandardSQLFunction("touches", + StandardBasicTypes.BOOLEAN)); + functionsToRegister.put("within", new StandardSQLFunction("within", + StandardBasicTypes.BOOLEAN)); + functionsToRegister.put("relate", new StandardSQLFunction("relate", + StandardBasicTypes.BOOLEAN)); + + // register the spatial analysis functions + functionsToRegister.put("distance", new StandardSQLFunction("distance", + StandardBasicTypes.DOUBLE)); + functionsToRegister.put("buffer", new StandardSQLFunction("buffer", + GeometryType.INSTANCE)); + functionsToRegister.put("convexhull", new StandardSQLFunction("convexhull", + GeometryType.INSTANCE)); + functionsToRegister.put("difference", new StandardSQLFunction("difference", + GeometryType.INSTANCE)); + functionsToRegister.put("intersection", new StandardSQLFunction( + "intersection", GeometryType.INSTANCE)); + functionsToRegister.put("symdifference", new StandardSQLFunction( + "symdifference", GeometryType.INSTANCE)); + functionsToRegister.put("geomunion", new StandardSQLFunction("union", + GeometryType.INSTANCE)); + return functionsToRegister; + } + + + + //TODO the getTypeName() override is necessary in the absence of HHH-6074 + @Override + public String getTypeName(int code, long length, int precision, int scale) throws HibernateException { + if (code == 3000 ) return "GEOMETRY"; + return super.getTypeName(code, length, precision, scale); + } + + @Override + public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) { + if ( sqlTypeDescriptor instanceof GeometrySqlTypeDescriptor) { + return MySQLGeometryTypeDescriptor.INSTANCE; + } + return super.remapSqlTypeDescriptor( sqlTypeDescriptor ); + } + + /** + * @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 + * SpatialRelation). + * @return + */ + public String getSpatialRelateSQL(String columnName, int spatialRelation) { + switch (spatialRelation) { + case SpatialRelation.WITHIN: + return " within(" + columnName + ",?)"; + case SpatialRelation.CONTAINS: + return " contains(" + columnName + ", ?)"; + case SpatialRelation.CROSSES: + return " crosses(" + columnName + ", ?)"; + case SpatialRelation.OVERLAPS: + return " overlaps(" + columnName + ", ?)"; + case SpatialRelation.DISJOINT: + return " disjoint(" + columnName + ", ?)"; + case SpatialRelation.INTERSECTS: + return " intersects(" + columnName + ", ?)"; + case SpatialRelation.TOUCHES: + return " touches(" + columnName + ", ?)"; + case SpatialRelation.EQUALS: + return " equals(" + columnName + ", ?)"; + default: + throw new IllegalArgumentException( + "Spatial relation is not known by this dialect"); + } + + } + + public String getSpatialFilterExpression(String columnName) { + return "MBRIntersects(" + columnName + ", ? ) "; + } + + public String getSpatialAggregateSQL(String columnName, int aggregation) { + throw new UnsupportedOperationException("Mysql has no spatial aggregate SQL functions."); + } + + public String getDWithinSQL(String columnName) { + throw new UnsupportedOperationException(String.format("Mysql doesn't support the Dwithin function")); + } + + public String getHavingSridSQL(String columnName) { + return " (srid(" + columnName + ") = ?) "; + } + + public String getIsEmptySQL(String columnName, boolean isEmpty) { + String emptyExpr = " IsEmpty(" + columnName + ") "; + return isEmpty ? emptyExpr : "( NOT " + emptyExpr + ")"; + } + + public String getDbGeometryTypeName() { + return "GEOMETRY"; + } + + public boolean supportsFiltering() { + return false; + } + + public boolean supports(SpatialFunction function) { + switch (function) { + case boundary: + case relate: + case distance: + case buffer: + case convexhull: + case difference: + case symdifference: + case intersection: + case geomunion: + case dwithin: + case transform: + return false; + } + return true; + } + +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLSpatialInnoDBDialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLSpatialInnoDBDialect.java new file mode 100644 index 0000000000..9087b9d317 --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLSpatialInnoDBDialect.java @@ -0,0 +1,120 @@ +/** + * 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.hibernate.spatial.dialect.mysql; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.MySQLInnoDBDialect; +import org.hibernate.dialect.function.StandardSQLFunction; +import org.hibernate.spatial.SpatialDialect; +import org.hibernate.spatial.SpatialFunction; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; + +import java.util.Iterator; +import java.util.Map; + +/** + * Extends the MySQLInnoDBDialect by also including information on spatial operators, + * constructors and processing functions. This is a mere wrapper class for dialect + * functionality defined in MySQLSpatialDialect + * + * @author Boni Gopalan + */ +public class MySQLSpatialInnoDBDialect extends MySQLInnoDBDialect implements SpatialDialect { + + + private MySQLSpatialDialect dialectDelegate = new MySQLSpatialDialect(); + + + public MySQLSpatialInnoDBDialect() { + super(); + Map functionsToRegister = dialectDelegate.getFunctionsToRegister(); + Map columnTypes = dialectDelegate.getColumnTypesToRegister(); + if (null != columnTypes) { + Iterator keys = columnTypes.keySet().iterator(); + while (keys.hasNext()) { + String aKey = keys.next(); + registerColumnType(columnTypes.get(aKey), aKey); + } + } + + if (null != functionsToRegister) { + Iterator keys = functionsToRegister.keySet().iterator(); + while (keys.hasNext()) { + String aKey = keys.next(); + registerFunction(aKey, functionsToRegister.get(aKey)); + + } + } + } + + @Override + public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) { + return dialectDelegate.remapSqlTypeDescriptor(sqlTypeDescriptor); + } + + @Override + public String getTypeName(int code, long length, int precision, int scale) throws HibernateException { + return dialectDelegate.getTypeName(code, length, precision, scale); + } + + public String getSpatialRelateSQL(String columnName, int spatialRelation) { + return dialectDelegate.getSpatialRelateSQL(columnName, spatialRelation); + } + + public String getSpatialFilterExpression(String columnName) { + return dialectDelegate.getSpatialFilterExpression(columnName); + } + + public String getSpatialAggregateSQL(String columnName, int aggregation) { + return dialectDelegate.getSpatialAggregateSQL(columnName, aggregation); + } + + public String getDWithinSQL(String columnName) { + return dialectDelegate.getDWithinSQL(columnName); + } + + public String getHavingSridSQL(String columnName) { + return dialectDelegate.getHavingSridSQL(columnName); + } + + public String getIsEmptySQL(String columnName, boolean isEmpty) { + return dialectDelegate.getIsEmptySQL(columnName, isEmpty); + } + + public String getDbGeometryTypeName() { + return dialectDelegate.getDbGeometryTypeName(); + } + + public boolean supportsFiltering() { + return dialectDelegate.supportsFiltering(); + } + + public boolean supports(SpatialFunction function) { + return dialectDelegate.supports(function); + } + +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java index b4f8227921..1c19944c41 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java @@ -1,47 +1,21 @@ package org.hibernate.spatial.dialect.oracle; -import java.sql.ResultSet; -import java.sql.SQLException; +import com.vividsolutions.jts.geom.*; +import org.hibernate.HibernateException; +import org.hibernate.spatial.Circle; +import org.hibernate.spatial.dialect.AbstractJTSGeometryValueExtractor; +import org.hibernate.spatial.jts.mgeom.MCoordinate; +import org.hibernate.spatial.jts.mgeom.MLineString; + import java.sql.Struct; import java.util.ArrayList; import java.util.List; -import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.geom.CoordinateSequence; -import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.geom.LineString; -import com.vividsolutions.jts.geom.LinearRing; -import com.vividsolutions.jts.geom.MultiLineString; -import com.vividsolutions.jts.geom.MultiPoint; -import com.vividsolutions.jts.geom.MultiPolygon; -import com.vividsolutions.jts.geom.Point; -import com.vividsolutions.jts.geom.Polygon; - -import org.hibernate.HibernateException; -import org.hibernate.spatial.Circle; -import org.hibernate.spatial.jts.JTS; -import org.hibernate.spatial.jts.mgeom.MCoordinate; -import org.hibernate.spatial.jts.mgeom.MGeometryFactory; -import org.hibernate.spatial.jts.mgeom.MLineString; -import org.hibernate.type.descriptor.ValueExtractor; -import org.hibernate.type.descriptor.WrapperOptions; - /** * @author Karel Maesen, Geovise BVBA * creation-date: 8/22/11 */ -public class SDOGeometryValueExtractor implements ValueExtractor { - - @Override - public Geometry extract(ResultSet rs, String name, WrapperOptions options) - throws SQLException { - Object geomObj = rs.getObject( name ); - return toJTS( geomObj ); - } - - public MGeometryFactory getGeometryFactory() { - return JTS.getDefaultGeomFactory(); - } +public class SDOGeometryValueExtractor extends AbstractJTSGeometryValueExtractor { public Geometry toJTS(Object struct) { if ( struct == null ) { diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PGGeometryValueBinder.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PGGeometryValueBinder.java index 998ba466db..aad5375cdc 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PGGeometryValueBinder.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PGGeometryValueBinder.java @@ -1,52 +1,21 @@ package org.hibernate.spatial.dialect.postgis; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Types; - import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; +import org.hibernate.spatial.dialect.AbstractJTSGeometryValueBinder; import org.hibernate.spatial.jts.JTS; -import org.postgis.GeometryCollection; -import org.postgis.LineString; -import org.postgis.LinearRing; -import org.postgis.MultiLineString; -import org.postgis.MultiPoint; -import org.postgis.MultiPolygon; -import org.postgis.PGgeometry; -import org.postgis.Point; -import org.postgis.Polygon; - import org.hibernate.spatial.jts.mgeom.MCoordinate; import org.hibernate.spatial.jts.mgeom.MGeometry; -import org.hibernate.spatial.jts.mgeom.MGeometryFactory; -import org.hibernate.type.descriptor.ValueBinder; -import org.hibernate.type.descriptor.WrapperOptions; +import org.postgis.*; + +import java.sql.Connection; /** * @author Karel Maesen, Geovise BVBA * creation-date: 7/27/11 */ -public class PGGeometryValueBinder implements ValueBinder { - - - @Override - public void bind(PreparedStatement st, Geometry value, int index, WrapperOptions options) throws SQLException { - if ( value == null ) { - st.setNull( index, Types.STRUCT ); - } - else { - Geometry jtsGeom = (Geometry) value; - Object dbGeom = toNative( jtsGeom, st.getConnection() ); - st.setObject( index, dbGeom ); - } - } - - public MGeometryFactory getGeometryFactory() { - return JTS.getDefaultGeomFactory(); - } +public class PGGeometryValueBinder extends AbstractJTSGeometryValueBinder { /** @@ -57,7 +26,7 @@ public class PGGeometryValueBinder implements ValueBinder { * * @return native database geometry object corresponding to jtsGeom. */ - private Object toNative(Geometry jtsGeom, Connection connection) { + protected Object toNative(Geometry jtsGeom, Connection connection) { org.postgis.Geometry geom = null; jtsGeom = forceEmptyToGeometryCollection( jtsGeom ); if ( jtsGeom instanceof com.vividsolutions.jts.geom.Point ) { diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PGGeometryValueExtractor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PGGeometryValueExtractor.java index 90f639a79d..f790c71e19 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PGGeometryValueExtractor.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PGGeometryValueExtractor.java @@ -1,41 +1,18 @@ package org.hibernate.spatial.dialect.postgis; -import java.sql.ResultSet; -import java.sql.SQLException; - import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; -import org.hibernate.spatial.jts.JTS; -import org.postgis.GeometryCollection; -import org.postgis.MultiLineString; -import org.postgis.MultiPoint; -import org.postgis.MultiPolygon; -import org.postgis.PGboxbase; -import org.postgis.PGgeometry; -import org.postgis.Point; -import org.postgis.Polygon; - +import org.hibernate.spatial.dialect.AbstractJTSGeometryValueExtractor; import org.hibernate.spatial.jts.mgeom.MCoordinate; -import org.hibernate.spatial.jts.mgeom.MGeometryFactory; import org.hibernate.spatial.jts.mgeom.MLineString; -import org.hibernate.type.descriptor.ValueExtractor; -import org.hibernate.type.descriptor.WrapperOptions; +import org.postgis.*; /** * @author Karel Maesen, Geovise BVBA * creation-date: 7/27/11 */ -public class PGGeometryValueExtractor implements ValueExtractor { +public class PGGeometryValueExtractor extends AbstractJTSGeometryValueExtractor { - @Override - public Geometry extract(ResultSet rs, String name, WrapperOptions options) throws SQLException { - Object geomObj = rs.getObject( name ); - return toJTS( geomObj ); - } - - public MGeometryFactory getGeometryFactory() { - return JTS.getDefaultGeomFactory(); - } public Geometry toJTS(Object object) { if ( object == null ) { @@ -199,7 +176,7 @@ public class PGGeometryValueExtractor implements ValueExtractor { return out; } - protected com.vividsolutions.jts.geom.Geometry convertPolygon( + private com.vividsolutions.jts.geom.Geometry convertPolygon( Polygon polygon) { com.vividsolutions.jts.geom.LinearRing shell = getGeometryFactory() .createLinearRing( @@ -222,14 +199,14 @@ public class PGGeometryValueExtractor implements ValueExtractor { return out; } - protected com.vividsolutions.jts.geom.Point convertPoint(Point pnt) { + private com.vividsolutions.jts.geom.Point convertPoint(Point pnt) { com.vividsolutions.jts.geom.Point g = getGeometryFactory().createPoint( this.toJTSCoordinate( pnt ) ); return g; } - protected com.vividsolutions.jts.geom.LineString convertLineString( + private com.vividsolutions.jts.geom.LineString convertLineString( org.postgis.LineString lstr) { com.vividsolutions.jts.geom.LineString out = lstr.haveMeasure ? getGeometryFactory() .createMLineString( toJTSCoordinates( lstr.getPoints() ) ) diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SQLServerGeometryUserType.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SQLServerGeometryUserType.java deleted file mode 100644 index 5a1752208f..0000000000 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SQLServerGeometryUserType.java +++ /dev/null @@ -1,81 +0,0 @@ -///* -// * $Id: SQLServerGeometryUserType.java 302 2011-05-07 18:23:11Z maesenka $ -// * -// * This file is part of Hibernate Spatial, an extension to the -// * hibernate ORM solution for geographic data. -// * -// * Copyright © 2007-2010 Geovise BVBA -// * -// * 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.sqlserver; -// -//import java.sql.Blob; -//import java.sql.Connection; -//import java.sql.SQLException; -//import java.sql.Types; -// -//import com.vividsolutions.jts.geom.Geometry; -//import org.hibernatespatial.AbstractDBGeometryType; -//import org.hibernatespatial.sqlserver.convertors.Decoders; -//import org.hibernatespatial.sqlserver.convertors.Encoders; -// -///** -// * The GeometryUserType for Microsoft SQL Server (2008). -// * -// * @author Karel Maesen, Geovise BVBA. -// */ -//public class SQLServerGeometryUserType extends AbstractDBGeometryType { -// -// public Geometry convert2JTS(Object obj) { -// byte[] raw = null; -// if ( obj == null ) { -// return null; -// } -// if ( ( obj instanceof byte[] ) ) { -// raw = (byte[]) obj; -// } -// else if ( obj instanceof Blob ) { -// raw = toByteArray( (Blob) obj ); -// } -// else { -// throw new IllegalArgumentException( "Expected byte array." ); -// } -// return Decoders.decode( raw ); -// } -// -// private byte[] toByteArray(Blob blob) { -// try { -// return blob.getBytes( 1, (int) blob.length() ); -// } -// catch ( SQLException e ) { -// throw new RuntimeException( "Error on transforming blob into array.", e ); -// } -// } -// -// public Object conv2DBGeometry(Geometry geom, Connection connection) { -// if ( geom == null ) { -// throw new IllegalArgumentException( "Null geometry passed." ); -// } -// return Encoders.encode( geom ); -// } -// -// public int[] sqlTypes() { -// return new int[] { Types.ARRAY }; -// } -//} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueExtractor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueExtractor.java index 045847d3ae..49392fa30d 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueExtractor.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/sqlserver/SqlServer2008GeometryValueExtractor.java @@ -1,32 +1,17 @@ package org.hibernate.spatial.dialect.sqlserver; -import java.sql.Blob; -import java.sql.ResultSet; -import java.sql.SQLException; - import com.vividsolutions.jts.geom.Geometry; - -import org.hibernate.spatial.jts.JTS; +import org.hibernate.spatial.dialect.AbstractJTSGeometryValueExtractor; import org.hibernate.spatial.dialect.sqlserver.convertors.Decoders; -import org.hibernate.spatial.jts.mgeom.MGeometryFactory; -import org.hibernate.type.descriptor.ValueExtractor; -import org.hibernate.type.descriptor.WrapperOptions; + +import java.sql.Blob; +import java.sql.SQLException; /** * @author Karel Maesen, Geovise BVBA * creation-date: 8/23/11 */ -public class SqlServer2008GeometryValueExtractor implements ValueExtractor { - - @Override - public Geometry extract(ResultSet rs, String name, WrapperOptions options) throws SQLException { - Object geomObj = rs.getObject( name ); - return toJTS( geomObj ); - } - - public MGeometryFactory getGeometryFactory() { - return JTS.getDefaultGeomFactory(); - } +public class SqlServer2008GeometryValueExtractor extends AbstractJTSGeometryValueExtractor { public Geometry toJTS(Object obj) { byte[] raw = null; diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/TestSupportFactories.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/TestSupportFactories.java index aab2452ad3..32b1fd711f 100644 --- a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/TestSupportFactories.java +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/TestSupportFactories.java @@ -1,6 +1,7 @@ package org.hibernate.spatial.testing; import org.hibernate.dialect.Dialect; +import org.hibernate.spatial.testing.dialects.mysql.MySQLTestSupport; import org.hibernate.spatial.testing.dialects.oracle.OracleSDOTestSupport; import org.hibernate.spatial.testing.dialects.postgis.PostgisTestSupport; import org.hibernate.spatial.testing.dialects.sqlserver.SQLServerTestSupport; @@ -39,6 +40,9 @@ public class TestSupportFactories { return this.getClass().getClassLoader(); } + //TODO -- find a better way to initialize and inject the TestSupport class. + //This whole class can probably be made obsolete. + private static Class getSupportFactoryClass(Dialect dialect) { String canonicalName = dialect.getClass().getCanonicalName(); if ("org.hibernate.spatial.dialect.postgis.PostgisDialect".equals(canonicalName)) { @@ -50,10 +54,10 @@ public class TestSupportFactories { if ("org.hibernate.spatial.dialect.sqlserver.SqlServer2008SpatialDialect".equals(canonicalName)) { return SQLServerTestSupport.class; } -// if ("org.hibernatespatial.mysql.MySQLSpatialDialect".equals(canonicalName) || -// "org.hibernatespatial.mysql.MySQLSpatialInnoDBDialect".equals(canonicalName)) { -// return "org.hibernatespatial.mysql.MySQLTestSupport"; -// } + if ("org.hibernate.spatial.dialect.mysql.MySQLSpatialDialect".equals(canonicalName) || + "org.hibernate.spatial.dialect.mysql.MySQLSpatialInnoDBDialect".equals(canonicalName)) { + return MySQLTestSupport.class; + } if ("org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect".equals(canonicalName)) { return OracleSDOTestSupport.class; } diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLExpectationsFactory.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLExpectationsFactory.java new file mode 100644 index 0000000000..604a7bb373 --- /dev/null +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLExpectationsFactory.java @@ -0,0 +1,235 @@ +/* + * $Id: MySQLExpectationsFactory.java 298 2011-03-12 15:29:54Z maesenka $ + * + * This file is part of Hibernate Spatial, an extension to the + * hibernate ORM solution for geographic data. + * + * Copyright © 2007-2010 Geovise BVBA + * + * 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.hibernate.spatial.testing.dialects.mysql; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Point; +import org.hibernate.spatial.dialect.mysql.MySQLGeometryValueExtractor; +import org.hibernate.spatial.testing.AbstractExpectationsFactory; +import org.hibernate.spatial.testing.DataSourceUtils; +import org.hibernate.spatial.testing.NativeSQLStatement; + + +/** + * This class provides the expected return values to the test classes in this package. + * + * @author Karel Maesen, Geovise BVBA + */ + +public class MySQLExpectationsFactory extends AbstractExpectationsFactory { + + private final MySQLGeometryValueExtractor decoder = new MySQLGeometryValueExtractor(); + + public MySQLExpectationsFactory(DataSourceUtils dataSourceUtils) { + super(dataSourceUtils); + } + + @Override + protected NativeSQLStatement createNativeTouchesStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, touches(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where touches(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeOverlapsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, overlaps(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where overlaps(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeRelateStatement(Geometry geom, String matrix) { + String sql = "select t.id, relate(t.geom, GeomFromText(?, 4326), '" + matrix + "' ) from GEOMTEST t where relate(t.geom, GeomFromText(?, 4326), '" + matrix + "') = 1 and srid(t.geom) = 4326"; + return createNativeSQLStatementAllWKTParams(sql, geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeDwithinStatement(Point geom, double distance) { + throw new UnsupportedOperationException(); + } + + @Override + protected NativeSQLStatement createNativeIntersectsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, intersects(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where intersects(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeFilterStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, MBRIntersects(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where MBRIntersects(t.geom, GeomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeDistanceStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, distance(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeDimensionSQL() { + return createNativeSQLStatement("select id, dimension(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeBufferStatement(Double distance) { + return createNativeSQLStatement("select t.id, buffer(t.geom,?) from GEOMTEST t where srid(t.geom) = 4326", new Object[]{distance}); + } + + @Override + protected NativeSQLStatement createNativeConvexHullStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, convexhull(geomunion(t.geom, GeomFromText(?, 4326))) from GEOMTEST t where srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeIntersectionStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, intersection(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeDifferenceStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, difference(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeSymDifferenceStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, symdifference(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeGeomUnionStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, geomunion(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeAsTextStatement() { + return createNativeSQLStatement("select id, astext(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeSridStatement() { + return createNativeSQLStatement("select id, srid(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeIsSimpleStatement() { + return createNativeSQLStatement("select id, issimple(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeIsEmptyStatement() { + return createNativeSQLStatement("select id, isempty(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeIsNotEmptyStatement() { + return createNativeSQLStatement("select id, not isempty(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeBoundaryStatement() { + return createNativeSQLStatement("select id, boundary(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeEnvelopeStatement() { + return createNativeSQLStatement("select id, envelope(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeAsBinaryStatement() { + return createNativeSQLStatement("select id, asbinary(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeGeometryTypeStatement() { + return createNativeSQLStatement("select id, GeometryType(geom) from GEOMTEST"); + } + + @Override + protected NativeSQLStatement createNativeWithinStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, within(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where within(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeEqualsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, equals(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where equals(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeCrossesStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, crosses(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where crosses(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeContainsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, contains(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where contains(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeDisjointStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, disjoint(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where disjoint(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeTransformStatement(int epsg) { + throw new UnsupportedOperationException(); + } + + @Override + protected NativeSQLStatement createNativeHavingSRIDStatement(int srid) { + return createNativeSQLStatement("select t.id, (srid(t.geom) = " + srid + ") from GEOMTEST t where SRID(t.geom) = " + srid); + } + + @Override + protected Geometry decode(Object o) { + return decoder.toJTS(o); + } +} diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLExpressionTemplate.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLExpressionTemplate.java new file mode 100644 index 0000000000..055e6bf17a --- /dev/null +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLExpressionTemplate.java @@ -0,0 +1,44 @@ +/* + * $Id: MySQLExpressionTemplate.java 190 2010-03-21 21:35:27Z maesenka $ + * + * This file is part of Hibernate Spatial, an extension to the + * hibernate ORM solution for geographic data. + * + * Copyright © 2007-2010 Geovise BVBA + * + * 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.hibernate.spatial.testing.dialects.mysql; + + +import org.hibernate.spatial.testing.SQLExpressionTemplate; +import org.hibernate.spatial.testing.TestDataElement; + +/** + * This is the template for insert SQL statements into the geomtest test table for MySQL. + * + * @author Karel Maesen, Geovise BVBA + */ +public class MySQLExpressionTemplate implements SQLExpressionTemplate { + + final String SQL_TEMPLATE = "insert into GEOMTEST values (%d, '%s', GeomFromText('%s', %d))"; + + public String toInsertSql(TestDataElement testDataElement) { + return String.format(SQL_TEMPLATE, testDataElement.id, testDataElement.type, testDataElement.wkt, testDataElement.srid); + } +} diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLGeometryEquality.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLGeometryEquality.java new file mode 100644 index 0000000000..6c7843c168 --- /dev/null +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLGeometryEquality.java @@ -0,0 +1,59 @@ +/* + * $Id: MySQLGeometryEquality.java 194 2010-03-26 15:56:45Z maesenka $ + * + * This file is part of Hibernate Spatial, an extension to the + * hibernate ORM solution for geographic data. + * + * Copyright © 2007-2010 Geovise BVBA + * + * 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.hibernate.spatial.testing.dialects.mysql; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import org.hibernate.spatial.testing.GeometryEquality; + +/** + * Extends the test for geometry equality, because + * MySQL stores empty geometries as NULL objects. + */ +public class MySQLGeometryEquality extends GeometryEquality { + + @Override + public boolean test(Geometry geom1, Geometry geom2) { + if (geom1 != null && geom1.isEmpty()) + return geom2 == null || geom2.isEmpty(); + return super.test(geom1, geom2); + } + + @Override + protected boolean testSimpleGeometryEquality(Geometry geom1, Geometry geom2) { + return testVerticesEquality(geom1, geom2); + } + + private boolean testVerticesEquality(Geometry geom1, Geometry geom2) { + if (geom1.getNumPoints() != geom2.getNumPoints()) return false; + for (int i = 0; i < geom1.getNumPoints(); i++) { + Coordinate cn1 = geom1.getCoordinates()[i]; + Coordinate cn2 = geom2.getCoordinates()[i]; + if (!cn1.equals2D(cn2)) return false; + } + return true; + } +} diff --git a/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLTestSupport.java b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLTestSupport.java new file mode 100644 index 0000000000..64bdf15938 --- /dev/null +++ b/hibernate-spatial/src/matrix/java/org/hibernate/spatial/testing/dialects/mysql/MySQLTestSupport.java @@ -0,0 +1,36 @@ +package org.hibernate.spatial.testing.dialects.mysql; + + +import org.hibernate.spatial.testing.*; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: Oct 18, 2010 + */ +public class MySQLTestSupport extends TestSupport { + + @Override + public TestData createTestData(BaseCoreFunctionalTestCase testcase) { + if (testcase.getClass().getCanonicalName().contains("TestSpatialFunctions") || + testcase.getClass().getCanonicalName().contains("TestSpatialRestrictions")) { + return TestData.fromFile("mysql/test-mysql-functions-data-set.xml"); + } + return TestData.fromFile("test-data-set.xml"); + } + + @Override + public AbstractExpectationsFactory createExpectationsFactory(DataSourceUtils dataSourceUtils) { + return new MySQLExpectationsFactory(dataSourceUtils); + } + + @Override + public GeometryEquality createGeometryEquality() { + return new MySQLGeometryEquality(); + } + + @Override + public SQLExpressionTemplate getSQLExpressionTemplate() { + return new MySQLExpressionTemplate(); + } +} diff --git a/hibernate-spatial/src/test/resources/hibernate.properties b/hibernate-spatial/src/test/resources/hibernate.properties index ac7d980c83..82d6245f1f 100644 --- a/hibernate-spatial/src/test/resources/hibernate.properties +++ b/hibernate-spatial/src/test/resources/hibernate.properties @@ -23,7 +23,7 @@ # # Default unit/integration test config. - +# hibernate.dialect org.hibernate.dialect.H2Dialect hibernate.connection.driver_class org.h2.Driver hibernate.connection.url jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE @@ -49,19 +49,19 @@ hibernate.jdbc.batch_versioned_data true #hibernate.connection.url jdbc:postgresql://localhost:5432:hibbrtru #hibernate.connection.username hibbrtru #hibernate.connection.password hibbrtru - +# #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.dialect org.hibernate.spatial.dialect.sqlserver.SqlServer2008SpatialDialect #hibernate.connection.driver_class com.microsoft.sqlserver.jdbc.SQLServerDriver #hibernate.connection.url jdbc:sqlserver://192.168.0.100:1433;databaseName=HBS #hibernate.connection.username hbs #hibernate.connection.password hbs -# + #hibernate.connection.pool_size 5 # #hibernate.show_sql true @@ -70,3 +70,25 @@ hibernate.jdbc.batch_versioned_data true # #hibernate.cache.region_prefix hibernate.test #hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory + +## +## MySQL 5 dialect +## +#hibernate.dialect org.hibernate.spatial.dialect.mysql.MySQLSpatialDialect +#hibernate.connection.driver_class com.mysql.jdbc.Driver +#hibernate.connection.url jdbc:mysql://localhost/testhbs +#hibernate.connection.username hibernate +#hibernate.connection.password hibernate +# +# +#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 + + diff --git a/hibernate-spatial/src/test/resources/mysql/test-mysql-functions-data-set.xml b/hibernate-spatial/src/test/resources/mysql/test-mysql-functions-data-set.xml new file mode 100644 index 0000000000..8d2c81ff4a --- /dev/null +++ b/hibernate-spatial/src/test/resources/mysql/test-mysql-functions-data-set.xml @@ -0,0 +1,144 @@ + + + + + 1 + POINT + POINT(10 5) + 4326 + + + 2 + POINT + POINT(52.25 2.53) + 4326 + + + + 3 + POINT + POINT(51 12) + 4326 + + + 4 + POINT + POINT(10.0 2.0) + 4326 + + + + 5 + LINESTRING + LINESTRING(10.0 5.0, 20.0 15.0) + 4326 + + + + 6 + LINESTRING + LINESTRING(10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0) + 4326 + + + + + 11 + MULTILINESTRING + MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0)) + 4326 + + + + 12 + MULTILINESTRING + MULTILINESTRING((10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0), (40.0 20.0, 42.0 18.0, 43.0 16.0, 40 14.0)) + + 4326 + + + + + 16 + POLYGON + POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) ) + 4326 + + + 18 + POLYGON + POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 5, 5 5,5 2, 2 2)) + 4326 + + + 19 + POLYGON + POLYGON( (110 110, 110 120, 120 120, 120 110, 110 110) ) + 4326 + + + + 20 + MULTIPOLYGON + MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 100, 120 140, 130 134, 105 100)) ) + 4326 + + + 22 + MULTIPOLYGON + MULTIPOLYGON(( (0 0, 0 50, 50 50, 50 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10) ),((105 100, 120 140, 130 + 134, 105 100)) ) + + 4326 + + + + + 25 + MULTIPOINT + MULTIPOINT(21 2, 25 5, 30 3) + 4326 + + + 26 + MULTIPOINT + MULTIPOINT(21 2) + 4326 + + + + 30 + GEOMETRYCOLLECTION + GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3)) + 4326 + + + 31 + GEOMETRYCOLLECTION + GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0))) + 4326 + + + 32 + GEOMETRYCOLLECTION + GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0),(1 1, 2 1, 2 2, 1 2, + 1 1))) + + 4326 + + + 33 + GEOMETRYCOLLECTION + GEOMETRYCOLLECTION( MULTIPOINT(21 2, 25 5, 30 3), MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 100, + 120 140, 130 134, 105 100)) ), MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0))) + + 4326 + + + +