diff --git a/jdbc/src/main/java/org/postgis/DriverWrapper.java b/jdbc/src/main/java/org/postgis/DriverWrapper.java index cab2552..2a04f65 100644 --- a/jdbc/src/main/java/org/postgis/DriverWrapper.java +++ b/jdbc/src/main/java/org/postgis/DriverWrapper.java @@ -1,12 +1,4 @@ /* - * DriverWrapper.java - * - * PostGIS extension for PostgreSQL JDBC driver - Wrapper utility class - * - * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com - * - * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com - * * 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 @@ -20,14 +12,17 @@ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * + * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com + * + * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com */ package org.postgis; + import java.sql.Connection; import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; @@ -35,6 +30,7 @@ import org.postgresql.Driver; import org.postgresql.PGConnection; + /** * DriverWrapper * @@ -73,6 +69,7 @@ */ public class DriverWrapper extends Driver { + /** The static logger instance. */ protected static final Logger logger = Logger.getLogger("org.postgis.DriverWrapper"); public static final String POSTGRES_PROTOCOL = "jdbc:postgresql:"; @@ -84,6 +81,17 @@ public class DriverWrapper extends Driver { protected TypesAdder typesAdder; + + static { + try { + // Try to register ourself to the DriverManager + java.sql.DriverManager.registerDriver(new DriverWrapper()); + } catch (SQLException e) { + logger.log(Level.WARNING, "Error registering PostGIS Wrapper Driver", e); + } + } + + /** * Default constructor. * @@ -101,7 +109,8 @@ public DriverWrapper() throws SQLException { } } - protected static TypesAdder getTypesAdder(Driver d) throws SQLException { + + protected static TypesAdder getTypesAdder(final Driver d) throws SQLException { if (d.getMajorVersion() == 7) { if (d.getMinorVersion() >= 3) { if (ta74 == null) { @@ -122,7 +131,8 @@ protected static TypesAdder getTypesAdder(Driver d) throws SQLException { } } - private static TypesAdder loadTypesAdder(String version) throws SQLException { + + private static TypesAdder loadTypesAdder(final String version) throws SQLException { try { Class klass = Class.forName("org.postgis.DriverWrapper$TypesAdder" + version); return (TypesAdder) klass.newInstance(); @@ -131,20 +141,13 @@ private static TypesAdder loadTypesAdder(String version) throws SQLException { } } - static { - try { - // Try to register ourself to the DriverManager - java.sql.DriverManager.registerDriver(new DriverWrapper()); - } catch (SQLException e) { - logger.log(Level.WARNING, "Error registering PostGIS Wrapper Driver", e); - } - } /** - * Creates a postgresql connection, and then adds the PostGIS data types to - * it calling addpgtypes() + * Creates a postgresql connection, and then adds the PostGIS data types to it calling addpgtypes(). + * + * A side-effect of this method is that the specified url parameter may be be changed * - * @param url the URL of the database to connect to + * @param url the URL of the database to connect to (may be changed as a side-effect of this method) * @param info a list of arbitrary tag/value pairs as connection arguments * @return a connection to the URL or null if it isnt us * @exception SQLException if a database access error occurs @@ -152,13 +155,14 @@ private static TypesAdder loadTypesAdder(String version) throws SQLException { * @see java.sql.Driver#connect * @see org.postgresql.Driver */ - public java.sql.Connection connect(String url, Properties info) throws SQLException { + public java.sql.Connection connect(String url, final Properties info) throws SQLException { url = mangleURL(url); Connection result = super.connect(url, info); typesAdder.addGT(result, useLW(result)); return result; } + /** * Do we have HexWKB as well known text representation - to be overridden by * subclasses. @@ -166,18 +170,21 @@ public java.sql.Connection connect(String url, Properties info) throws SQLExcept * @param result Connection to check * @return true if using EWKB, false otherwise */ - protected boolean useLW(Connection result) { + protected boolean useLW(final Connection result) { if (result == null) { throw new IllegalArgumentException("null is no valid parameter"); } return false; } + /** * Check whether the driver thinks he can handle the given URL. + * + * A side-effect of this method is that the specified url parameter may be be changed * * @see java.sql.Driver#acceptsURL - * @param url the URL of the driver + * @param url the URL of the driver (may be changed as a side-effect of this method) * @return true if this driver accepts the given URL */ public boolean acceptsURL(String url) { @@ -189,6 +196,7 @@ public boolean acceptsURL(String url) { return super.acceptsURL(url); } + /** * Returns our own CVS version plus postgres Version * @@ -198,6 +206,7 @@ public static String getVersion() { return "PostGisWrapper " + REVISION + ", wrapping " + Driver.getVersion(); } + /* * Here follows the addGISTypes() stuff. This is a little tricky because the * pgjdbc people had several, partially incompatible API changes during 7.2 @@ -214,30 +223,33 @@ public static String getVersion() { * @throws SQLException when a SQLException occurs * */ - public static void addGISTypes(PGConnection pgconn) throws SQLException { + public static void addGISTypes(final PGConnection pgconn) throws SQLException { loadTypesAdder("74").addGT((Connection) pgconn, false); } + /** * adds the JTS/PostGIS Data types to a PG 8.0+ Connection. * * @param pgconn The PGConnection object to add the types to * @throws SQLException when a SQLException occurs */ - public static void addGISTypes80(PGConnection pgconn) throws SQLException { + public static void addGISTypes80(final PGConnection pgconn) throws SQLException { loadTypesAdder("80").addGT((Connection) pgconn, false); } + /** * adds the JTS/PostGIS Data types to a PG 7.2 Connection. * * @param pgconn The PGConnection object to add the types to * @throws SQLException when a SQLException occurs */ - public static void addGISTypes72(org.postgresql.PGConnection pgconn) throws SQLException { + public static void addGISTypes72(final org.postgresql.PGConnection pgconn) throws SQLException { loadTypesAdder("72").addGT((Connection) pgconn, false); } + /** * Mangles the PostGIS URL to return the original PostGreSQL URL * @@ -245,7 +257,7 @@ public static void addGISTypes72(org.postgresql.PGConnection pgconn) throws SQLE * @return "mangled" string * @throws SQLException when a SQLException occurs */ - protected String mangleURL(String url) throws SQLException { + protected String mangleURL(final String url) throws SQLException { String myProgo = getProtoString(); if (url.startsWith(myProgo)) { return POSTGRES_PROTOCOL + url.substring(myProgo.length()); @@ -254,13 +266,15 @@ protected String mangleURL(String url) throws SQLException { } } + protected String getProtoString() { return POSTGIS_PROTOCOL; } + /** Base class for the three typewrapper implementations */ protected abstract static class TypesAdder { - public final void addGT(java.sql.Connection conn, boolean lw) throws SQLException { + public final void addGT(final java.sql.Connection conn, final boolean lw) throws SQLException { if (lw) { addBinaryGeometries(conn); } else { @@ -269,68 +283,88 @@ public final void addGT(java.sql.Connection conn, boolean lw) throws SQLExceptio addBoxen(conn); } - public abstract void addGeometries(Connection conn) throws SQLException; + public abstract void addGeometries(final Connection conn) throws SQLException; - public abstract void addBoxen(Connection conn) throws SQLException; + public abstract void addBoxen(final Connection conn) throws SQLException; - public abstract void addBinaryGeometries(Connection conn) throws SQLException; + public abstract void addBinaryGeometries(final Connection conn) throws SQLException; } + /** addGISTypes for V7.3 and V7.4 pgjdbc */ protected static final class TypesAdder74 extends TypesAdder { - public void addGeometries(Connection conn) throws SQLException { + + /** {@inheritDoc} */ + @Override + public void addGeometries(final Connection conn) throws SQLException { PGConnection pgconn = (PGConnection) conn; pgconn.addDataType("geometry", org.postgis.PGgeometry.class); pgconn.addDataType("public.geometry", org.postgis.PGgeometry.class); pgconn.addDataType("\"public\".\"geometry\"", org.postgis.PGgeometry.class); - pgconn.addDataType("geography", org.postgis.PGgeometry.class); - pgconn.addDataType("public.geography", org.postgis.PGgeometry.class); - pgconn.addDataType("\"public\".\"geography\"", org.postgis.PGgeometry.class); + pgconn.addDataType("geography", org.postgis.PGgeography.class); + pgconn.addDataType("public.geography", org.postgis.PGgeography.class); + pgconn.addDataType("\"public\".\"geography\"", org.postgis.PGgeography.class); } - public void addBoxen(Connection conn) throws SQLException { + /** {@inheritDoc} */ + @Override + public void addBoxen(final Connection conn) throws SQLException { PGConnection pgconn = (PGConnection) conn; pgconn.addDataType("box3d", org.postgis.PGbox3d.class); pgconn.addDataType("box2d", org.postgis.PGbox2d.class); } - public void addBinaryGeometries(Connection conn) throws SQLException { + /** {@inheritDoc} */ + @Override + public void addBinaryGeometries(final Connection conn) throws SQLException { PGConnection pgconn = (PGConnection) conn; pgconn.addDataType("geometry", org.postgis.PGgeometryLW.class); - pgconn.addDataType("geography", org.postgis.PGgeometryLW.class); + pgconn.addDataType("geography", org.postgis.PGgeographyLW.class); } } + /** addGISTypes for V7.2 pgjdbc */ protected static class TypesAdder72 extends TypesAdder { - public void addGeometries(Connection conn) throws SQLException { + + /** {@inheritDoc} */ + @Override + public void addGeometries(final Connection conn) throws SQLException { org.postgresql.PGConnection pgconn = (org.postgresql.PGConnection) conn; pgconn.addDataType("geometry", org.postgis.PGgeometry.class); pgconn.addDataType("public.geometry", org.postgis.PGgeometry.class); pgconn.addDataType("\"public\".\"geometry\"", org.postgis.PGgeometry.class); - pgconn.addDataType("geography", org.postgis.PGgeometry.class); - pgconn.addDataType("public.geography", org.postgis.PGgeometry.class); - pgconn.addDataType("\"public\".\"geography\"", org.postgis.PGgeometry.class); + pgconn.addDataType("geography", org.postgis.PGgeography.class); + pgconn.addDataType("public.geography", org.postgis.PGgeography.class); + pgconn.addDataType("\"public\".\"geography\"", org.postgis.PGgeography.class); } - public void addBoxen(Connection conn) throws SQLException { + /** {@inheritDoc} */ + @Override + public void addBoxen(final Connection conn) throws SQLException { org.postgresql.PGConnection pgconn = (org.postgresql.PGConnection) conn; pgconn.addDataType("box3d", org.postgis.PGbox3d.class); pgconn.addDataType("box2d", org.postgis.PGbox2d.class); } - public void addBinaryGeometries(Connection conn) throws SQLException { + /** {@inheritDoc} */ + @Override + public void addBinaryGeometries(final Connection conn) throws SQLException { org.postgresql.PGConnection pgconn = (org.postgresql.PGConnection) conn; pgconn.addDataType("geometry", org.postgis.PGgeometryLW.class); - pgconn.addDataType("geography", org.postgis.PGgeometryLW.class); + pgconn.addDataType("geography", org.postgis.PGgeographyLW.class); } } + /** addGISTypes for V8.0 (and hopefully newer) pgjdbc */ protected static class TypesAdder80 extends TypesAdder { - public void addGeometries(Connection conn) throws SQLException { + + /** {@inheritDoc} */ + @Override + public void addGeometries(final Connection conn) throws SQLException { PGConnection pgconn = (PGConnection) conn; pgconn.addDataType("geometry", org.postgis.PGgeometry.class); pgconn.addDataType("public.geometry", org.postgis.PGgeometry.class); @@ -341,20 +375,29 @@ public void addGeometries(Connection conn) throws SQLException { pgconn.addDataType("\"public\".\"geography\"", org.postgis.PGgeometry.class); } - public void addBoxen(Connection conn) throws SQLException { + /** {@inheritDoc} */ + @Override + public void addBoxen(final Connection conn) throws SQLException { PGConnection pgconn = (PGConnection) conn; pgconn.addDataType("box3d", org.postgis.PGbox3d.class); pgconn.addDataType("box2d", org.postgis.PGbox2d.class); } - public void addBinaryGeometries(Connection conn) throws SQLException { + /** {@inheritDoc} */ + @Override + public void addBinaryGeometries(final Connection conn) throws SQLException { PGConnection pgconn = (PGConnection) conn; pgconn.addDataType("geometry", org.postgis.PGgeometryLW.class); - pgconn.addDataType("geography", org.postgis.PGgeometryLW.class); + pgconn.addDataType("geography", org.postgis.PGgeographyLW.class); } } + + /** {@inheritDoc} */ + @Override public Logger getParentLogger() { throw new UnsupportedOperationException("Not supported yet."); } + + } diff --git a/jdbc/src/main/java/org/postgis/PGgeo.java b/jdbc/src/main/java/org/postgis/PGgeo.java new file mode 100644 index 0000000..e1a2ac3 --- /dev/null +++ b/jdbc/src/main/java/org/postgis/PGgeo.java @@ -0,0 +1,133 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * (C) 2004 Paul Ramsey, pramsey@refractions.net + * + * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com + * + * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com + */ + +package org.postgis; + + +import org.postgis.binary.BinaryParser; +import org.postgresql.util.PGobject; + +import java.sql.SQLException; + + +/** + * A PostgreSQL JDBC PGobject extension data type modeling a "geo" type. + * + * This class serves as a common superclass for classes such as PGgeometry and PGgeography which model + * more specific type semantics. + * + * @author Phillip Ross + */ +public class PGgeo extends PGobject { + + private static final long serialVersionUID = -3181366908975582090L; + + /** The encapsulated geometry. */ + Geometry geometry; + + + /** Instantiate with default state. */ + protected PGgeo() { + } + + + /** + * Instantiate with the specified state. + * + * @param geometry the geometry to instantiate with + */ + public PGgeo(final Geometry geometry) { + this(); + this.geometry = geometry; + } + + + /** + * Instantiate with the specified state. + * + * @param value the value to instantiate with + */ + public PGgeo(final String value) throws SQLException { + this(); + setValue(value); + } + + + /** {@inheritDoc} */ + @Override + public String getValue() { + return geometry.toString(); + } + + + /** {@inheritDoc} */ + @Override + public void setValue(final String value) throws SQLException { + geometry = GeometryBuilder.geomFromString(value, new BinaryParser()); + } + + + /** + * Get the encapsulated geometry. + * + * @return the encapsulated geomtery + */ + public Geometry getGeometry() { + return geometry; + } + + + /** + * Set the encapsulated geometry. + * + * @param geometry the encapsulated geometry + */ + public void setGeometry(final Geometry geometry) { + this.geometry = geometry; + } + + + /** + * Get the type of the encapsulated geometry. + * + * @return the type of the encapsulated geometry + */ + public int getGeoType() { + return geometry.type; + } + + + /** {@inheritDoc} */ + @Override + public String toString() { + return geometry.toString(); + } + + + /** {@inheritDoc} */ + @Override + public Object clone() { + return new PGgeo(geometry); + } + + +} diff --git a/jdbc/src/main/java/org/postgis/PGgeography.java b/jdbc/src/main/java/org/postgis/PGgeography.java new file mode 100644 index 0000000..30f5647 --- /dev/null +++ b/jdbc/src/main/java/org/postgis/PGgeography.java @@ -0,0 +1,77 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * (C) 2004 Paul Ramsey, pramsey@refractions.net + * + * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com + * + * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com + */ + +package org.postgis; + + +import java.sql.SQLException; + + +/** + * A PostgreSQL JDBC PGobject extension data type modeling the geography type. + * + * @author Phillip Ross + */ +public class PGgeography extends PGgeo { + + private static final long serialVersionUID = 3796853960196603896L; + + + /** Instantiate with default state. */ + public PGgeography() { + super(); + setType("geography"); + } + + + /** + * Instantiate with the specified state. + * + * @param geometry the geometry to instantiate with + */ + public PGgeography(final Geometry geometry) { + this(); + this.geometry = geometry; + setType("geography"); + } + + + /** + * Instantiate with the specified state. + * + * @param value the value to instantiate with + */ + public PGgeography(final String value) throws SQLException { + this(); + setValue(value); + setType("geography"); + } + + + /** {@inheritDoc} */ + @Override + public Object clone() { + return new PGgeography(geometry); + } + + +} diff --git a/jdbc/src/main/java/org/postgis/PGgeographyLW.java b/jdbc/src/main/java/org/postgis/PGgeographyLW.java new file mode 100644 index 0000000..a64b7d4 --- /dev/null +++ b/jdbc/src/main/java/org/postgis/PGgeographyLW.java @@ -0,0 +1,84 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com + * + * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com + */ + +package org.postgis; + + +import org.postgis.binary.BinaryWriter; + +import java.sql.SQLException; + + +/** + * A PostgreSQL JDBC PGobject extension data type modeling the geography type. + * + * The hex-encoded EWKB format is used to communicate with the backend, which is much more efficient, + * but only works with Lwgeom enabled PostGIS (1.0.0 and up). + * + * @author Phillip Ross + */ +public class PGgeographyLW extends PGgeography { + + private static final long serialVersionUID = 7717856818804158022L; + + /** The binary writer to be used for serializing geometry to a PGobject value. */ + BinaryWriter bw = new BinaryWriter(); + + + /** Instantiate with default state. */ + public PGgeographyLW() { + super(); + } + + /** + * Instantiate with the specified state. + * + * @param geometry the geometry to instantiate with + */ + public PGgeographyLW(final Geometry geometry) { + super(geometry); + } + + + /** + * Instantiate with the specified state. + * + * @param value the value to instantiate with + */ + public PGgeographyLW(final String value) throws SQLException { + super(value); + } + + + /** {@inheritDoc} */ + @Override + public String getValue() { + return bw.writeHexed(geometry); + } + + + /** {@inheritDoc} */ + @Override + public Object clone() { + return new PGgeographyLW(geometry); + } + + +} diff --git a/jdbc/src/main/java/org/postgis/PGgeometry.java b/jdbc/src/main/java/org/postgis/PGgeometry.java index 8f80450..acd96ca 100644 --- a/jdbc/src/main/java/org/postgis/PGgeometry.java +++ b/jdbc/src/main/java/org/postgis/PGgeometry.java @@ -1,14 +1,4 @@ /* - * PGgeometry.java - * - * PostGIS extension for PostgreSQL JDBC driver - PGobject Geometry Wrapper - * - * (C) 2004 Paul Ramsey, pramsey@refractions.net - * - * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com - * - * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com - * * 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 @@ -23,62 +13,63 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * (C) 2004 Paul Ramsey, pramsey@refractions.net + * + * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com + * + * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com */ package org.postgis; -import org.postgis.binary.BinaryParser; -import org.postgresql.util.PGobject; - import java.sql.SQLException; -public class PGgeometry extends PGobject { - /* JDK 1.5 Serialization */ - private static final long serialVersionUID = 0x100; +/** + * A PostgreSQL JDBC PGobject extension data type modeling the geometry type. + * + * @author Phillip Ross + */ +public class PGgeometry extends PGgeo { + + private static final long serialVersionUID = 4116907189503026815L; - Geometry geom; + /** Instantiate with default state. */ public PGgeometry() { - this.setType("geometry"); + super(); + setType("geometry"); } - public PGgeometry(Geometry geom) { - this(); - this.geom = geom; - } - public PGgeometry(String value) throws SQLException { - this(); - setValue(value); + /** + * Instantiate with the specified state. + * + * @param geometry the geometry to instantiate with + */ + public PGgeometry(final Geometry geometry) { + super(geometry); + setType("geometry"); } - public void setValue(String value) throws SQLException { - geom = GeometryBuilder.geomFromString(value, new BinaryParser()); - } - public Geometry getGeometry() { - return geom; + /** + * Instantiate with the specified state. + * + * @param value the value to instantiate with + */ + public PGgeometry(final String value) throws SQLException { + super(value); + setType("geometry"); } - public void setGeometry(Geometry newgeom) { - this.geom = newgeom; - } - public int getGeoType() { - return geom.type; - } - - public String toString() { - return geom.toString(); + /** {@inheritDoc} */ + @Override + public Object clone() { + return new PGgeometry(geometry); } - public String getValue() { - return geom.toString(); - } - public Object clone() { - return new PGgeometry(geom); - } } diff --git a/jdbc/src/main/java/org/postgis/PGgeometryLW.java b/jdbc/src/main/java/org/postgis/PGgeometryLW.java index 72b3e0e..b66c9fc 100644 --- a/jdbc/src/main/java/org/postgis/PGgeometryLW.java +++ b/jdbc/src/main/java/org/postgis/PGgeometryLW.java @@ -1,12 +1,4 @@ /* - * PGgeometryLW.java - * - * PostGIS extension for PostgreSQL JDBC driver - PGobject LWGeometry Wrapper - * - * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com - * - * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com - * * 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 @@ -20,48 +12,74 @@ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * + * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com + * + * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com */ package org.postgis; + import org.postgis.binary.BinaryWriter; import java.sql.SQLException; + /** - * This is a subclas of PGgeometry that uses hex encoded EWKB to communicate - * with the backend, which is much more efficient, but only works with Lwgeom - * enabled PostGIS (1.0.0 and up). + * A PostgreSQL JDBC PGobject extension data type modeling the geometry type. + * + * The hex-encoded EWKB format is used to communicate with the backend, which is much more efficient, + * but only works with Lwgeom enabled PostGIS (1.0.0 and up). + * + * @author Phillip Ross */ - public class PGgeometryLW extends PGgeometry { - /* JDK 1.5 Serialization */ - private static final long serialVersionUID = 0x100; - + + private static final long serialVersionUID = -7774502289413094862L; + + /** The binary writer to be used for serializing geometry to a PGobject value. */ BinaryWriter bw = new BinaryWriter(); + + /** Instantiate with default state. */ public PGgeometryLW() { super(); } - public PGgeometryLW(Geometry geom) { - super(geom); + + /** + * Instantiate with the specified state. + * + * @param geometry the geometry to instantiate with + */ + public PGgeometryLW(final Geometry geometry) { + super(geometry); } - public PGgeometryLW(String value) throws SQLException { + + /** + * Instantiate with the specified state. + * + * @param value the value to instantiate with + */ + public PGgeometryLW(final String value) throws SQLException { super(value); } - public String toString() { - return geom.toString(); - } + /** {@inheritDoc} */ + @Override public String getValue() { - return bw.writeHexed(geom); + return bw.writeHexed(geometry); } + + /** {@inheritDoc} */ + @Override public Object clone() { - return new PGgeometryLW(geom); + return new PGgeometryLW(geometry); } + + } diff --git a/jdbc/src/main/resources/org/postgresql/driverconfig.properties b/jdbc/src/main/resources/org/postgresql/driverconfig.properties index 1e744c1..62ee9e7 100644 --- a/jdbc/src/main/resources/org/postgresql/driverconfig.properties +++ b/jdbc/src/main/resources/org/postgresql/driverconfig.properties @@ -4,5 +4,6 @@ # datatype.geometry=org.postgis.PGgeometry +datatype.geography=org.postgis.PGgeography datatype.box3d=org.postgis.PGbox3d datatype.box2d=org.postgis.PGbox2d diff --git a/jdbc/src/test/java/org/postgis/AutoRegistrationTest.java b/jdbc/src/test/java/org/postgis/AutoRegistrationTest.java deleted file mode 100644 index 8278ebb..0000000 --- a/jdbc/src/test/java/org/postgis/AutoRegistrationTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * AutoRegistrationTest.java - * - * PostGIS extension for PostgreSQL JDBC driver - example and test classes - * - * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -package org.postgis; - - -import net.postgis.tools.testutils.TestContainerController; -import org.postgresql.Driver; -import org.postgresql.util.PGobject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.ITestContext; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import java.sql.*; - - -/** - * This test program tests whether the autoregistration of PostGIS data type within the postgresql jdbc driver was - * successful. It also checks for PostGIS version to know whether box2d is available. - */ -public class AutoRegistrationTest { - - private static final Logger logger = LoggerFactory.getLogger(AutoRegistrationTest.class); - - private Connection connection; - - @Test - public void testAutoRegistration(ITestContext ctx) throws Exception { - logger.debug("Driver version: {}", Driver.getVersion()); - int major = new Driver().getMajorVersion(); - Assert.assertTrue(major >= 8, "postgresql driver " + major + ".X is too old, it does not support auto-registration"); - - Statement statement = connection.createStatement(); - int postgisServerMajor = getPostgisMajor(statement); - logger.debug("PostGIS Version: " + postgisServerMajor); - Assert.assertNotEquals(postgisServerMajor, 0, "Could not get PostGIS version. Is PostGIS really installed in the database?"); - - // Test geometries - ResultSet resultSet = statement.executeQuery("SELECT 'POINT(1 2)'::geometry"); - resultSet.next(); - PGobject result = (PGobject) resultSet.getObject(1); - Assert.assertTrue(result instanceof PGgeometry); - - // Test box3d - resultSet = statement.executeQuery("SELECT 'BOX3D(1 2 3, 4 5 6)'::box3d"); - resultSet.next(); - result = (PGobject) resultSet.getObject(1); - Assert.assertTrue(result instanceof PGbox3d); - - // Test box2d if appropriate - if (postgisServerMajor < 1) { - logger.info("PostGIS version is too old, skipping box2ed test"); - } else { - resultSet = statement.executeQuery("SELECT 'BOX(1 2,3 4)'::box2d"); - resultSet.next(); - result = (PGobject) resultSet.getObject(1); - Assert.assertTrue(result instanceof PGbox2d); - } - } - - - public static int getPostgisMajor(Statement statement) throws SQLException { - ResultSet resultSet = statement.executeQuery("SELECT postgis_version()"); - resultSet.next(); - String version = resultSet.getString(1); - if (version == null) { - throw new SQLException("postgis_version returned NULL!"); - } - version = version.trim(); - int idx = version.indexOf('.'); - return Integer.parseInt(version.substring(0, idx)); - } - - - @BeforeClass - public void initJdbcConnection(ITestContext ctx) throws Exception { - final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX); - Assert.assertNotNull(jdbcUrlSuffix); - final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix; - final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME); - Assert.assertNotNull(jdbcUsername); - final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME); - Assert.assertNotNull(jdbcPassword); - connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword); - } - - - @AfterClass - public void shutdown() throws Exception { - logger.debug("shutting down"); - if (connection != null) { - connection.close(); - } - } - - -} \ No newline at end of file diff --git a/jdbc/src/test/java/org/postgis/DatatypesAutoRegistrationTest.java b/jdbc/src/test/java/org/postgis/DatatypesAutoRegistrationTest.java new file mode 100644 index 0000000..7f5d4ff --- /dev/null +++ b/jdbc/src/test/java/org/postgis/DatatypesAutoRegistrationTest.java @@ -0,0 +1,144 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com + * + * (C) 2020 Phillip Ross, phillip.w.g.ross@gmail.com + */ + +package org.postgis; + + +import net.postgis.tools.testutils.TestContainerController; +import org.postgis.util.VersionUtil; +import org.postgresql.Driver; +import org.postgresql.util.PGobject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.ITestContext; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; + + +/** + * This test program tests whether the auto-registration of PostGIS data types within the postgresql jdbc driver was + * successful. It also checks for PostGIS version to know whether box2d is available. + */ +public class DatatypesAutoRegistrationTest { + + /** The static logger instance. */ + private static final Logger logger = LoggerFactory.getLogger(DatatypesAutoRegistrationTest.class); + + /** The JDBC Connection to be used for tests. */ + private Connection connection; + + + /** + * Initializes a new JDBC Connection. + * + * @param ctx the test context + * @throws Exception when an exception occurs + */ + @BeforeMethod + public void initJdbcConnection(ITestContext ctx) throws Exception { + logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName()); + final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX); + Assert.assertNotNull(jdbcUrlSuffix); + final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix; + final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME); + Assert.assertNotNull(jdbcUsername); + final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME); + Assert.assertNotNull(jdbcPassword); + connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword); + } + + + /** + * Un-allocates the JDBC connection. + * + * @throws Exception when an exception occurs + */ + @AfterMethod + public void shutdown() throws Exception { + logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName()); + logger.debug("shutting down"); + if (connection != null) { + connection.close(); + } + } + + + @Test + public void testAutoRegistration() throws Exception { + logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName()); + Driver driver = new Driver(); + int driverMajorVersion = driver.getMajorVersion(); + int driverMinorVersion = driver.getMinorVersion(); + logger.debug("Driver version: {}.{}", driverMajorVersion, driverMinorVersion); + if (driverMajorVersion < 8) { + logger.info( + "postgresql driver {}.{} is too old, it does not support auto-registration", + driverMajorVersion, driverMinorVersion + ); + } else { + int postgisServerMajor = Integer.parseInt(VersionUtil.retrievePostGISServerMajorVersion(connection)); + logger.debug("PostGIS Version: " + postgisServerMajor); + Assert.assertNotEquals( + postgisServerMajor, + 0, + "Could not get PostGIS version. Is PostGIS really installed in the database?" + ); + Statement statement = connection.createStatement(); + + // Test geometries + ResultSet resultSet = statement.executeQuery("SELECT 'POINT(1 2)'::geometry"); + resultSet.next(); + PGobject result = (PGobject) resultSet.getObject(1); + Assert.assertTrue(result instanceof PGgeometry); + + // Test geography + resultSet = statement.executeQuery("SELECT 'POINT(1 2)'::geography"); + resultSet.next(); + Object geographyRawObject = resultSet.getObject(1); + result = (PGobject) resultSet.getObject(1); + Assert.assertTrue(result instanceof PGgeography); + + // Test box3d + resultSet = statement.executeQuery("SELECT 'BOX3D(1 2 3, 4 5 6)'::box3d"); + resultSet.next(); + result = (PGobject) resultSet.getObject(1); + Assert.assertTrue(result instanceof PGbox3d); + + // Test box2d if appropriate + if (postgisServerMajor < 1) { + logger.info("PostGIS version is too old, skipping box2ed test"); + } else { + resultSet = statement.executeQuery("SELECT 'BOX(1 2,3 4)'::box2d"); + resultSet.next(); + result = (PGobject) resultSet.getObject(1); + Assert.assertTrue(result instanceof PGbox2d); + } + } + } + + +} diff --git a/jdbc/src/test/java/org/postgis/DatatypesTest.java b/jdbc/src/test/java/org/postgis/DatatypesTest.java index 4bc8090..284f4f0 100644 --- a/jdbc/src/test/java/org/postgis/DatatypesTest.java +++ b/jdbc/src/test/java/org/postgis/DatatypesTest.java @@ -51,4 +51,13 @@ public void testPGgeometry() throws SQLException { } + @Test + public void testPGgeography() throws SQLException { + logger.trace("void testPGgeography()"); + logger.info(mlng_str); + PGgeography pgf = new PGgeography(mlng_str); + logger.info(pgf.toString()); + } + + } \ No newline at end of file diff --git a/jdbc/src/test/java/org/postgis/EmptyGeometriesTest.java b/jdbc/src/test/java/org/postgis/EmptyGeometriesTest.java index ef7efbb..a321a94 100644 --- a/jdbc/src/test/java/org/postgis/EmptyGeometriesTest.java +++ b/jdbc/src/test/java/org/postgis/EmptyGeometriesTest.java @@ -65,7 +65,8 @@ public class EmptyGeometriesTest { public static final String[] castTypes = new String[] { "bytea", "text", - "geometry" + "geometry", + "geography" }; private Connection connection = null; @@ -83,7 +84,7 @@ public void testSqlStatements() throws SQLException { ResultSet resultSet = preparedStatement.executeQuery() ) { resultSet.next(); - for (int i = 1; i <= 3; i++) { + for (int i = 1; i <= castTypes.length; i++) { Object resultSetObject = resultSet.getObject(i); logger.debug("returned resultSetObject {} => (class=[{}]) {}", i, resultSetObject.getClass().getName(), resultSetObject); } diff --git a/jdbc/src/test/java/org/postgis/GeographyDatatypeTest.java b/jdbc/src/test/java/org/postgis/GeographyDatatypeTest.java new file mode 100644 index 0000000..58ead35 --- /dev/null +++ b/jdbc/src/test/java/org/postgis/GeographyDatatypeTest.java @@ -0,0 +1,260 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * (C) 2020 Phillip Ross, phillip.w.g.ross@gmail.com + */ + +package org.postgis; + + +import net.postgis.tools.testutils.TestContainerController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.ITestContext; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.util.UUID; + + +/** + * Integration tests for PGgeography. + * + * @author Phillip Ross + */ +public class GeographyDatatypeTest { + + /** The static logger instance. */ + private static final Logger logger = LoggerFactory.getLogger(GeographyDatatypeTest.class); + + /** The jdbc url prefix containing the jdbc protocol to be used for tests. */ + private static final String JDBC_URL_PROTOCOL_PREFIX = "jdbc:postgresql"; + + /** The jdbc url prefix containing the jdbc lightweight protocol to be used for tests. */ + private static final String JDBC_URL_LW_PROTOCOL_PREFIX = "jdbc:postgresql_lwgis"; + + /** The prefix for database tables used in the tests. */ + private static final String DATABASE_TABLE_NAME_PREFIX = "jdbc_test"; + + /** Test geometries dataset. */ + public static final String[] testGeometries = new String[] { + "POINT(10 10)", // 2D + "POINT(10 10 0)", // 3D with 3rd coordinate set to 0 + "POINT(10 10 20)", // 3D + "POINT(1e100 1.2345e-100 -2e-5)", // 3D with scientific notation + "POINTM(10 10 20)", // 2D + Measures + "POINT(10 10 20 30)", // 3D + Measures + "MULTIPOINT(11 12, 20 20)", // broken format, see http://lists.jump-project.org/pipermail/jts-devel/2006-April/001572.html + "MULTIPOINT(11 12 13, 20 20 20)", // broken format + "MULTIPOINTM(11 12 13, 20 20 20)", // broken format + "MULTIPOINT(11 12 13 14,20 20 20 20)", // broken format + "MULTIPOINT((11 12), (20 20))", // OGC conforming format + "MULTIPOINT((11 12 13), (20 20 20))", + "MULTIPOINTM((11 12 13), (20 20 20))", + "MULTIPOINT((11 12 13 14),(20 20 20 20))", + "LINESTRING(10 10,20 20,50 50,34 34)", + "LINESTRING(10 10 20,20 20 20,50 50 50,34 34 34)", + "LINESTRINGM(10 10 20,20 20 20,50 50 50,34 34 34)", + "LINESTRING(10 10 20 20,20 20 20 20,50 50 50 50,34 34 34 50)", + "POLYGON((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))", + "POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))", + "POLYGONM((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))", + "POLYGON((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7))", + "MULTIPOLYGON(((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)),((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)))", + "MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", + "MULTIPOLYGONM(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", + "MULTIPOLYGON(((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7)),((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7)))", + "MULTILINESTRING((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))", + "MULTILINESTRING((10 10 5,20 10 5,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))", + "MULTILINESTRINGM((10 10 7,20 10 7,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))", + "MULTILINESTRING((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7))", + "GEOMETRYCOLLECTION(POINT(10 10),POINT(20 20))", + "GEOMETRYCOLLECTION(POINT(10 10 20),POINT(20 20 20))", + "GEOMETRYCOLLECTION(POINT(10 10 20 7),POINT(20 20 20 7))", + "GEOMETRYCOLLECTION(LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34))", + "GEOMETRYCOLLECTION(POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", + "GEOMETRYCOLLECTION(MULTIPOINT(10 10 10, 20 20 20),MULTIPOINT(10 10 10, 20 20 20))", // Cannot be parsed by 0.X servers, broken format + "GEOMETRYCOLLECTION(MULTIPOINT((10 10 10), (20 20 20)),MULTIPOINT((10 10 10), (20 20 20)))", // Cannot be parsed by 0.X servers, OGC conformant + "GEOMETRYCOLLECTION(MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", // PostGIs 0.X "flattens" this geometry, so it is not equal after reparsing. + "GEOMETRYCOLLECTION(MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))))", // PostGIs 0.X "flattens" this geometry, so it is not equal after reparsing. + "GEOMETRYCOLLECTION(POINT(10 10 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", + "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT(10 10 10, 20 20 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", // Collections that contain both X and MultiX do not work on PostGIS 0.x, broken format + "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT((10 10 10), (20 20 20)),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", // Collections that contain both X and MultiX do not work on PostGIS 0.x, OGC conformant + "GEOMETRYCOLLECTION EMPTY", // new (correct) representation + "GEOMETRYCOLLECTIONM(POINTM(10 10 20),POINTM(20 20 20))" + }; + + /** The JDBC Connection to be used for tests. */ + private Connection connection = null; + + /** The JDBC Connection w/ lightweight protocol to be used for tests. */ + private Connection connectionLW = null; + + + /** + * Initializes a new JDBC Connection. + * + * @param ctx the test context + * @throws Exception when an exception occurs + */ + @BeforeMethod + public void initJdbcConnection(ITestContext ctx) throws Exception { + final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX); + Assert.assertNotNull(jdbcUrlSuffix); + final String jdbcUrl = JDBC_URL_PROTOCOL_PREFIX + jdbcUrlSuffix; + final String jdbcUrlLW = JDBC_URL_LW_PROTOCOL_PREFIX + jdbcUrlSuffix; + final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME); + Assert.assertNotNull(jdbcUsername); + final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME); + Assert.assertNotNull(jdbcPassword); + Class.forName("org.postgis.DriverWrapperLW"); + connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword); + connectionLW = DriverManager.getConnection(jdbcUrlLW, jdbcUsername, jdbcPassword); + } + + + /** + * Un-allocates the JDBC connection. + * + * @throws Exception when an exception occurs + */ + @AfterMethod + public void unallocateDatabaseResources() throws Exception { + if ((connection != null) && (!connection.isClosed())) { + connection.close(); + } + if ((connectionLW != null) && (!connectionLW.isClosed())) { + connection.close(); + } + } + + + /** + * Test inserting geometries into the database with prepared statements and querying back the results with + * both geometry/geography and standard/lightweight. + * + * @throws Exception when an exception occurs. + */ + @Test + public void testDatatypes() throws Exception { + + final String testTableName = DATABASE_TABLE_NAME_PREFIX + + "_" + + UUID.randomUUID() + .toString() + .replaceAll("-", ""); + + final String dropTableSQL = "drop table " + testTableName; + + final String createTableSQL = "create table " + testTableName + + " ( _id numeric," + + " geometry_value geometry, geometrylw_value geometry," + + " geography_value geography, geographylw_value geography)"; + final int idColumnIndex = 1; + final int geometryValueColumnIndex = 2; + final int geometrylwValueColumnIndex = 3; + final int geographyValueColumnIndex = 4; + final int geographylwValueColumnIndex = 5; + + final String insertSQL = "insert into " + testTableName + " ( " + + "_id, geometry_value, geometrylw_value, " + + "geography_value, geographylw_value) " + + "values ( ?, ?, ?, ?, ? )"; + + boolean tableExists = false; + DatabaseMetaData databaseMetaData = connection.getMetaData(); + try ( + ResultSet resultSet = databaseMetaData.getTables( + null, null, testTableName.toLowerCase(), new String[] { "TABLE" } + ) + ) { + while (resultSet.next()) { + tableExists = true; + } + } + + if (tableExists) { + logger.debug("Dropping pre-existing test table..."); + try (Statement statement = connection.createStatement()) { + statement.executeQuery(dropTableSQL); + } + } + + logger.debug("Creating test table..."); + try (Statement statement = connection.createStatement()) { + statement.execute(createTableSQL); + } + + + logger.debug("Inserting test geometries into table..."); + try (PreparedStatement preparedStatement = connection.prepareStatement(insertSQL)) { + for (int i = 0; i < testGeometries.length; i++) { + PGgeometry geometry = new PGgeometry(testGeometries[i]); + PGgeometryLW geometryLW = new PGgeometryLW(testGeometries[i]); + PGgeography geography = new PGgeography(testGeometries[i]); + PGgeographyLW geographyLW = new PGgeographyLW(testGeometries[i]); + + preparedStatement.setInt(idColumnIndex, i); + preparedStatement.setObject(geometryValueColumnIndex, geometry); + preparedStatement.setObject(geometrylwValueColumnIndex, geometryLW); + preparedStatement.setObject(geographyValueColumnIndex, geography); + preparedStatement.setObject(geographylwValueColumnIndex, geographyLW); + preparedStatement.executeUpdate(); + } + } + + logger.debug("Querying table with standard connection..."); + try ( + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery( + "select _id, geometry_value, geometrylw_value, geography_value, geographylw_value from " + + testTableName + ) + ) { + while (resultSet.next()) { + Assert.assertEquals(resultSet.getObject(geometryValueColumnIndex).getClass(), PGgeometry.class); + Assert.assertEquals(resultSet.getObject(geometrylwValueColumnIndex).getClass(), PGgeometry.class); + Assert.assertEquals(resultSet.getObject(geographyValueColumnIndex).getClass(), PGgeography.class); + Assert.assertEquals(resultSet.getObject(geographylwValueColumnIndex).getClass(), PGgeography.class); + } + } + + logger.debug("Querying table with lightweight connection..."); + try ( + Statement statement = connectionLW.createStatement(); + ResultSet resultSet = statement.executeQuery( + "select _id, geometry_value, geometrylw_value, geography_value, geographylw_value from " + + testTableName + ) + ) { + while (resultSet.next()) { + Assert.assertEquals(resultSet.getObject(geometryValueColumnIndex).getClass(), PGgeometryLW.class); + Assert.assertEquals(resultSet.getObject(geometrylwValueColumnIndex).getClass(), PGgeometryLW.class); + Assert.assertEquals(resultSet.getObject(geographyValueColumnIndex).getClass(), PGgeographyLW.class); + Assert.assertEquals(resultSet.getObject(geographylwValueColumnIndex).getClass(), PGgeographyLW.class); + } + } + } + + +} \ No newline at end of file diff --git a/jdbc/src/test/resources-filtered/testng-it.xml b/jdbc/src/test/resources-filtered/testng-it.xml index 5097955..dae6101 100644 --- a/jdbc/src/test/resources-filtered/testng-it.xml +++ b/jdbc/src/test/resources-filtered/testng-it.xml @@ -11,9 +11,10 @@ - + + diff --git a/postgis-geometry/src/test/resources/testng.xml b/postgis-geometry/src/test/resources/testng.xml index 4a55e81..0169ee0 100644 --- a/postgis-geometry/src/test/resources/testng.xml +++ b/postgis-geometry/src/test/resources/testng.xml @@ -1,7 +1,7 @@ - +