From 71a093e7b78f3082850c3a3b313b64bc9516054c Mon Sep 17 00:00:00 2001 From: Lonny Date: Tue, 4 Mar 2014 18:23:40 -0700 Subject: [PATCH 1/6] Added the initial support for Derby. All but one unit test work in both H2 and Derby. --- app/pom.xml | 3 +- core/pom.xml | 39 +- core/src/main/java/geodb/GeoDB.java | 278 ++++++++++-- .../geodb/aggregate/GeoAggregateFunction.java | 49 +- core/src/main/resources/geodb/geodb.sql | 60 --- core/src/main/resources/geodb/geodb_derby.sql | 425 ++++++++++++++++++ core/src/main/resources/geodb/geodb_h2.sql | 60 +++ .../test/java/geodb/DatabaseTestUtils.java | 72 +++ core/src/test/java/geodb/DerbyTestUtils.java | 72 +++ core/src/test/java/geodb/GeoDBDerbyTest.java | 50 +++ .../geodb/GeoDBExtraFunctionsDerbyTest.java | 48 ++ .../java/geodb/GeoDBExtraFunctionsH2Test.java | 64 +++ .../java/geodb/GeoDBFunctionDerbyTest.java | 48 ++ .../test/java/geodb/GeoDBFunctionH2Test.java | 43 ++ core/src/test/java/geodb/GeoDBH2Test.java | 42 ++ core/src/test/java/geodb/GeoDBTest.java | 73 --- .../src/test/java/geodb/GeoDBTestSupport.java | 78 +++- core/src/test/java/geodb/H2TestUtils.java | 60 +++ core/src/test/java/geodb/TestGeoDB.java | 83 ++++ ...Test.java => TestGeoDBExtraFunctions.java} | 56 +-- ...nctionTest.java => TestGeoDBFunction.java} | 49 +- .../aggregate/AggregateFunctionDerbyTest.java | 51 +++ .../aggregate/AggregateFunctionH2Test.java | 47 ++ ...onTest.java => TestAggregateFunction.java} | 28 +- pom.xml | 2 +- 25 files changed, 1624 insertions(+), 256 deletions(-) delete mode 100644 core/src/main/resources/geodb/geodb.sql create mode 100644 core/src/main/resources/geodb/geodb_derby.sql create mode 100644 core/src/main/resources/geodb/geodb_h2.sql create mode 100644 core/src/test/java/geodb/DatabaseTestUtils.java create mode 100644 core/src/test/java/geodb/DerbyTestUtils.java create mode 100644 core/src/test/java/geodb/GeoDBDerbyTest.java create mode 100644 core/src/test/java/geodb/GeoDBExtraFunctionsDerbyTest.java create mode 100644 core/src/test/java/geodb/GeoDBExtraFunctionsH2Test.java create mode 100644 core/src/test/java/geodb/GeoDBFunctionDerbyTest.java create mode 100644 core/src/test/java/geodb/GeoDBFunctionH2Test.java create mode 100644 core/src/test/java/geodb/GeoDBH2Test.java delete mode 100644 core/src/test/java/geodb/GeoDBTest.java create mode 100644 core/src/test/java/geodb/H2TestUtils.java create mode 100644 core/src/test/java/geodb/TestGeoDB.java rename core/src/test/java/geodb/{GeoDBExtraFunctionsTest.java => TestGeoDBExtraFunctions.java} (80%) rename core/src/test/java/geodb/{GeoDBFunctionTest.java => TestGeoDBFunction.java} (83%) create mode 100644 core/src/test/java/geodb/aggregate/AggregateFunctionDerbyTest.java create mode 100644 core/src/test/java/geodb/aggregate/AggregateFunctionH2Test.java rename core/src/test/java/geodb/aggregate/{AggregateFunctionTest.java => TestAggregateFunction.java} (74%) diff --git a/app/pom.xml b/app/pom.xml index 014ca45..158edf1 100644 --- a/app/pom.xml +++ b/app/pom.xml @@ -5,10 +5,9 @@ org.opengeo geodb-parent - 0-SNAPSHOT + 0.9-SNAPSHOT - org.opengeo geodb-app jar GeoDB App diff --git a/core/pom.xml b/core/pom.xml index edd92bb..b0bceb4 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -5,10 +5,9 @@ org.opengeo geodb-parent - 0-SNAPSHOT + 0.9-SNAPSHOT - org.opengeo geodb jar GeoDB Core @@ -35,6 +34,18 @@ 4.7 test + + org.apache.derby + derby + 10.10.1.1 + true + + + commons-io + commons-io + 2.4 + test + @@ -46,6 +57,30 @@ 1.5 + + maven-surefire-plugin + + + org.h2.Driver + jdbc:h2:target/geodb + + + + + Test Derby + test + + test + + + + org.apache.derby.jdbc.EmbeddedDriver + jdbc:derby:directory:target/geodb;create=true + + + + + maven-source-plugin diff --git a/core/src/main/java/geodb/GeoDB.java b/core/src/main/java/geodb/GeoDB.java index 191a486..c3954f8 100644 --- a/core/src/main/java/geodb/GeoDB.java +++ b/core/src/main/java/geodb/GeoDB.java @@ -7,6 +7,7 @@ import java.io.InputStreamReader; import java.sql.Connection; import java.sql.DatabaseMetaData; +import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -89,16 +90,31 @@ public static String Version() { return "9"; } + // + // Database initializer + // + public static void InitGeoDBProc() throws SQLException { + final Connection connection = DriverManager.getConnection("jdbc:default:connection"); + InitGeoDB(connection); + } + // // Database initializer // public static void InitGeoDB(Connection cx) throws SQLException { try { + final String scriptSuffix; + final String geoDbTableName = getGeoDBTableName(cx); + if (isH2(cx)) { + scriptSuffix = "_h2"; + } else { + scriptSuffix = "_derby"; + } Statement st = cx.createStatement(); try { //first check if this database is already spatial and up to date try { - ResultSet rs = st.executeQuery("SELECT checksum FROM _GEODB"); + ResultSet rs = st.executeQuery("SELECT checksum FROM " + geoDbTableName); try { //table exists, check the checksum if (rs.next()) { @@ -117,23 +133,38 @@ public static void InitGeoDB(Connection cx) throws SQLException { catch (SQLException e) { //first time, continue with initialization } - - //load h2 functions + + //load h2/derby functions BufferedReader in = new BufferedReader( - new InputStreamReader(GeoDB.class.getResourceAsStream("geodb.sql"))); + new InputStreamReader(GeoDB.class.getResourceAsStream("geodb" + scriptSuffix + ".sql"))); String line = null; + String fullLine = ""; while((line = in.readLine()) != null) { - try { - st.execute(line); + line = line.trim(); + // Skip lines that start with a '#'. + if (line.startsWith("#") || line.length() == 0) { + continue; } - catch(SQLException e) { - //ignore + if (fullLine == null) { + fullLine = line; + } else { + fullLine += ' ' + line; + } + if (line.endsWith(";")) { + fullLine = fullLine.substring(0, fullLine.lastIndexOf(';')); + try { + CmdLine.LOGGER.log(Level.FINE, "Executing line : " + fullLine); + st.execute(fullLine); + } catch (SQLException e) { + // ignore + } + fullLine = null; } } in.close(); //load hatbox functions - List ddl = CmdLine.getddl("create_h2.sql"); + List ddl = CmdLine.getddl("create" + scriptSuffix + ".sql"); for (Iterator i = ddl.iterator(); i.hasNext(); ) { line = i.next(); try { @@ -144,15 +175,19 @@ public static void InitGeoDB(Connection cx) throws SQLException { } } - //create the _GEOH2 metadata table - st.execute("CREATE TABLE IF NOT EXISTS _GEODB (checksum VARCHAR)"); - st.execute("DELETE FROM _GEODB"); - st.execute("INSERT INTO _GEODB VALUES (" + Version() + ")" ); - + //create the GeoDB metadata table + if (tableExists(cx, null, geoDbTableName, "TABLE")) { + st.execute("DROP TABLE " + geoDbTableName); + } + st.execute("CREATE TABLE " + geoDbTableName + " (checksum VARCHAR(4))"); + st.execute("INSERT INTO " + geoDbTableName + " VALUES ('" + Version() + "')" ); + //create the geometry columns table - st.execute("CREATE TABLE IF NOT EXISTS geometry_columns (f_table_schema VARCHAR, " + - "f_table_name VARCHAR, f_geometry_column VARCHAR, coord_dimension INT, " + - "srid INT, type VARCHAR(30))"); + if (!tableExists(cx, null, "geometry_columns", "TABLE")) { + st.execute("CREATE TABLE geometry_columns (f_table_schema VARCHAR(128), " + + "f_table_name VARCHAR(128), f_geometry_column VARCHAR(128), coord_dimension INTEGER, " + + "srid INTEGER, type VARCHAR(30))"); + } } finally { st.close(); @@ -162,10 +197,45 @@ public static void InitGeoDB(Connection cx) throws SQLException { throw (SQLException) new SQLException("Could not initialize database").initCause(e); } } - + + /** + * Returns the appropriate GeoDB table name for the given connection. + * + * @param cx + * the database connection. + * @return the GeoDB table name. + * @throws SQLException + * if unable to extract the database product name from the + * connection. + */ + public static String getGeoDBTableName(Connection cx) throws SQLException { + if (isH2(cx)) { + return "_GEODB"; + } else { + return "GEODB_"; + } + } + // // Management functions // + /** + * Adds a geometry column to a table. + * + * @param schema The table schema, may be null to specify default schema + * @param table The table name, not null + * @param column The geometry column name, not null + * @param srid The spatial reference system identifier + * @param type The geometry type, one of "POINT", "LINESTRING", "POLYGON", "MULTIPOINT", + * "MULTILINESTRING", "MULTIPOLYGON", "GEOMETRY", "GEOMETRYCOLLECTION" + * @param dim The geometry dimension + */ + public static void AddGeometryColumnProc(String schema, String table, + String column, int srid, String type, int dim) throws SQLException { + Connection cx = DriverManager.getConnection("jdbc:default:connection"); + AddGeometryColumn(cx, schema, table, column, srid, type, dim); + } + /** * Adds a geometry column to a table. * @@ -188,19 +258,36 @@ public static void AddGeometryColumn(Connection cx, String schema, String table, cx.getMetaData().getColumns(null, schema, table, column); try { if (!rs.next()) { - st.execute("ALTER TABLE " + tbl(schema, table) + " ADD " - + esc(column) + " " + type + " COMMENT '" + type + "'"); + StringBuilder sql = new StringBuilder(); + sql.append("ALTER TABLE ").append(tbl(schema, table)); + sql.append(" ADD COLUMN ").append(esc(column)).append(' ') + .append(getType(cx, type)); + if (isH2(cx)) { + sql.append(" COMMENT '").append(getType(cx, type)).append("'"); + } + st.execute(sql.toString()); } } finally { rs.close(); } - - schema = schema != null ? schema : "PUBLIC"; + + if (schema == null) { + schema = getDefaultSchema(cx); + } if (!"GEOMETRY".equals(type) && !"GEOMETRYCOLLECTION".equals(type)) { - st.execute("ALTER TABLE " + tbl(schema, table) + " ADD CONSTRAINT " + - esc(geotypeConstraint(schema,table,column)) + " CHECK " + esc(column) + - " IS NULL OR " + "GeometryType(" + esc(column) + ") = '" + type + "'"); + String sql = "ALTER TABLE " + tbl(schema, table) + + " ADD CONSTRAINT " + + esc(geotypeConstraint(schema, table, column)) + + " CHECK "; + if (isH2(cx)) { + sql += esc(column) + " IS NULL OR " + + "GeometryType(" + esc(column) + ") = '" + type + "'";} + else { + sql += "(" + esc(column) + " IS NULL OR " + + "GeometryType(" + esc(column) + ") = '" + type + "')"; + } + st.execute(sql); } st.execute("INSERT INTO geometry_columns VALUES (" + str(schema) + ", " + str(table) + ", " + str(column) + ", " + @@ -210,7 +297,15 @@ public static void AddGeometryColumn(Connection cx, String schema, String table, st.close(); } } - + + private static Object getType(Connection cx, String type) + throws SQLException { + if (isH2(cx)) { + return type; + } + return "VARCHAR (32672) FOR BIT DATA"; + } + /** * Drops a geometry column from a table. * @@ -218,24 +313,58 @@ public static void AddGeometryColumn(Connection cx, String schema, String table, * @param table The table name, not null * @param column The geometry column name, not null */ + public static void DropGeometryColumnProc(String schema, String table, String column) + throws SQLException { + Connection cx = DriverManager.getConnection("jdbc:default:connection"); + DropGeometryColumn(cx, schema, table, column); + } + + /** + * Drops a geometry column from a table. + * + * @param cx The database connection + * @param schema The table schema, may be null to specify default schema + * @param table The table name, not null + * @param column The geometry column name, not null + */ public static void DropGeometryColumn(Connection cx, String schema, String table, String column) throws SQLException { Statement st = cx.createStatement(); try { //check the case of a view - boolean isView = false; - ResultSet tables = cx.getMetaData().getTables(null, schema, table, new String[]{"VIEW"}); - try { - isView = tables.next(); + boolean isView = tableExists(cx, schema, table, "VIEW"); + + if (schema == null) { + schema = getDefaultSchema(cx); } - finally { - tables.close(); + final String constraintName = geotypeConstraint(schema,table,column); + boolean constraintExists = true; + String ifExistsClause = ""; + if (isH2(cx)) { + ifExistsClause = "IF EXISTS "; + } else { + // Query the Derby SYS schema to determine if the constraint already exists. + StringBuilder sql = new StringBuilder(); + sql.append("SELECT * FROM SYS.SYSSCHEMAS s INNER JOIN SYS.SYSTABLES t "); + sql.append("ON s.SCHEMANAME = ").append(str(schema)); + sql.append(" AND t.TABLENAME = ").append(str(table)); + sql.append(" AND s.SCHEMAID = t.SCHEMAID INNER JOIN SYS.SYSCONSTRAINTS c "); + sql.append("ON c.CONSTRAINTNAME = ").append(str(constraintName)); + sql.append(" AND c.TABLEID = t.TABLEID"); + ResultSet rs = st.executeQuery(sql.toString()); + try { + constraintExists = rs.next(); + } + finally { + rs.close(); + } } - schema = schema != null ? schema : "PUBLIC"; - st.execute("ALTER TABLE " + tbl(schema, table) + " DROP CONSTRAINT IF EXISTS " - + esc(geotypeConstraint(schema,table,column))); + if (constraintExists) { + st.execute("ALTER TABLE " + tbl(schema, table) + " DROP CONSTRAINT " + ifExistsClause + + esc(constraintName)); + } if (!isView) { st.execute("ALTER TABLE " + tbl(schema, table) + " DROP COLUMN " + esc(column)); @@ -255,10 +384,24 @@ public static void DropGeometryColumn(Connection cx, String schema, String table * @param schema The table schema, may be null to specify default schema * @param table The table name, not null */ + public static void DropGeometryColumnsProc(String schema, String table) throws SQLException { + Connection cx = DriverManager.getConnection("jdbc:default:connection"); + DropGeometryColumns(cx, schema, table); + } + + /** + * Drops all the geometry columns from a table. + * + * @param cx The database connection + * @param schema The table schema, may be null to specify default schema + * @param table The table name, not null + */ public static void DropGeometryColumns(Connection cx, String schema, String table) throws SQLException { Statement st = cx.createStatement(); try { - schema = schema != null ? schema : "PUBLIC"; + if (schema == null) { + schema = getDefaultSchema(cx); + } //look up the geometry column entries StringBuffer sql = new StringBuffer(); @@ -276,7 +419,7 @@ public static void DropGeometryColumns(Connection cx, String schema, String tabl st.close(); } } - + // // Geometry Outputs // @@ -358,7 +501,7 @@ public static byte[] ST_GeomFromEWKT (String wkt) { return gToWKB(gFromEWKT(wkt)); } - + /** * Return a specified ST_Geometry value from Well-Known Text representation (WKT). */ @@ -1048,11 +1191,16 @@ public static byte[] ST_Union(byte[] wkb1, byte[] wkb2) { // // Management functions // + public static void CreateSpatialIndexProc( String schemaName, String tableName, + String columnName, String srid) throws SQLException { + final Connection connection = DriverManager.getConnection("jdbc:default:connection"); + CreateSpatialIndex(connection, schemaName, tableName, columnName, srid); + } public static void CreateSpatialIndex( Connection cx, String schemaName, String tableName, String columnName, String srid) throws SQLException { HashMap args = new HashMap(); if (schemaName == null) { - schemaName = "PUBLIC"; + schemaName = getDefaultSchema(cx); } args.put("s", schemaName); @@ -1101,7 +1249,7 @@ public static void DropSpatialIndex( Connection cx, String schemaName, String ta HashMap args = new HashMap(); if (schemaName == null) { - schemaName = "PUBLIC"; + schemaName = getDefaultSchema(cx); } args.put("s", schemaName); @@ -1281,6 +1429,56 @@ public static int GetSRID( Connection cx, String schemaName, String tableName ) // // helper/utility functions // + + /** + * Determines if the current database is H2. + * @param cx the database connection. + * @return true if the database connection is to H2. + * @throws SQLException if unable to fetch the database metadata. + */ + public static boolean isH2(Connection cx) throws SQLException { + return "H2".equalsIgnoreCase(cx.getMetaData().getDatabaseProductName()); + } + + /** + * Returns the default schema name depending upon the type of database. + * @param cx the database connection. + * @return the default schema name. + * @throws SQLException if unable to fetch the database metadata. + */ + public static String getDefaultSchema(Connection cx) throws SQLException { + return isH2(cx) ? "PUBLIC" : cx.getMetaData().getUserName().toUpperCase(); + } + + /** + * Determines if the specified table exists. + * + * @param cx + * the database connection. + * @param schemaName + * the schema name or null. + * @param tableName + * the table name. + * @param types + * the array of table types (see + * {@link DatabaseMetaData#getTableTypes() getTableTypes()}) or + * null for all types. + * @return true if the table exists. + * @throws SQLException + * if unable to query the database. + */ + public static boolean tableExists(Connection cx, String schemaName, + String tableName, String... types) throws SQLException { + boolean exists = false; + ResultSet rs = cx.getMetaData().getTables(null, schemaName, tableName.toUpperCase(), types); + try { + exists = rs.next(); + } finally { + rs.close(); + } + return exists; + } + public static byte[] gToWKB( Geometry g ) { return wkbwriter().write( g ); } diff --git a/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java b/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java index 4ee509f..3f52456 100644 --- a/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java +++ b/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java @@ -4,9 +4,12 @@ import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; +import java.sql.Connection; import java.sql.SQLException; import java.sql.Types; +import org.apache.derby.agg.Aggregator; import org.h2.api.AggregateFunction; import com.vividsolutions.jts.geom.Geometry; @@ -14,9 +17,9 @@ import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKBReader; -public abstract class GeoAggregateFunction implements AggregateFunction { +public abstract class GeoAggregateFunction implements AggregateFunction, Aggregator { - private Geometry createGeometry(ByteArrayInputStream stream) { + private Geometry createGeometry(InputStream stream) { InputStreamInStream inputStreamInStream = new InputStreamInStream(stream); Geometry geometry = null; try { @@ -43,7 +46,7 @@ public final void add(Object arg0) throws SQLException { } } - public final Object getResult() throws SQLException { + public final Object getResult() { Geometry geometryResult = getGeometryResult(); if (geometryResult != null) { return GeoDB.gToWKB(geometryResult); @@ -55,4 +58,44 @@ public final int getType(int[] arg0) throws SQLException { return Types.BLOB; } + /** + * @see org.apache.derby.agg.Aggregator#init() + */ + public void init() { + } + + /** + * @see org.apache.derby.agg.Aggregator#accumulate(java.lang.Object) + */ + public void accumulate(byte[] array) { + if (array != null) { + Geometry geometry = createGeometry(new ByteArrayInputStream(array)); + if (geometry != null) { + add(geometry); + } + } + } + + /** + * @see org.apache.derby.agg.Aggregator#merge(org.apache.derby.agg.Aggregator) + */ + public void merge(GeoAggregateFunction function) { + add(function.getGeometryResult()); + } + + /** + * @see org.apache.derby.agg.Aggregator#terminate() + */ + public byte[] terminate() { + return (byte[])getResult(); + } + + /** + * @see org.h2.api.AggregateFunction#init(java.sql.Connection) + */ + public void init(Connection arg0) throws SQLException { + // TODO Auto-generated method stub + + } + } \ No newline at end of file diff --git a/core/src/main/resources/geodb/geodb.sql b/core/src/main/resources/geodb/geodb.sql deleted file mode 100644 index 5fea34a..0000000 --- a/core/src/main/resources/geodb/geodb.sql +++ /dev/null @@ -1,60 +0,0 @@ -CREATE ALIAS AddGeometryColumn for "geodb.GeoDB.AddGeometryColumn" -CREATE ALIAS CreateSpatialIndex for "geodb.GeoDB.CreateSpatialIndex" -CREATE ALIAS DropGeometryColumn for "geodb.GeoDB.DropGeometryColumn" -CREATE ALIAS DropGeometryColumns for "geodb.GeoDB.DropGeometryColumns" -CREATE ALIAS DropSpatialIndex for "geodb.GeoDB.DropSpatialIndex" -CREATE ALIAS EnvelopeAsText for "geodb.GeoDB.EnvelopeAsText" -CREATE ALIAS GeometryType for "geodb.GeoDB.GeometryType" -CREATE ALIAS ST_Area FOR "geodb.GeoDB.ST_Area" -CREATE ALIAS ST_AsEWKB FOR "geodb.GeoDB.ST_AsEWKB" -CREATE ALIAS ST_AsEWKT FOR "geodb.GeoDB.ST_AsEWKT" -CREATE ALIAS ST_AsHexEWKB FOR "geodb.GeoDB.ST_AsHexEWKB" -CREATE ALIAS ST_AsText FOR "geodb.GeoDB.ST_AsText" -CREATE ALIAS ST_BBOX FOR "geodb.GeoDB.ST_BBox" -CREATE ALIAS ST_Boundary FOR "geodb.GeoDB.ST_Boundary" -CREATE ALIAS ST_Buffer FOR "geodb.GeoDB.ST_Buffer" -CREATE ALIAS ST_Centroid FOR "geodb.GeoDB.ST_Centroid" -CREATE ALIAS ST_Crosses FOR "geodb.GeoDB.ST_Crosses" -CREATE ALIAS ST_Contains FOR "geodb.GeoDB.ST_Contains" -CREATE ALIAS ST_ConvexHull FOR "geodb.GeoDB.ST_ConvexHull" -CREATE ALIAS ST_DWithin FOR "geodb.GeoDB.ST_DWithin" -CREATE ALIAS ST_Disjoint FOR "geodb.GeoDB.ST_Disjoint" -CREATE ALIAS ST_Distance FOR "geodb.GeoDB.ST_Distance" -CREATE ALIAS ST_Difference FOR "geodb.GeoDB.ST_Difference" -CREATE ALIAS ST_Dimension FOR "geodb.GeoDB.ST_Dimension" -CREATE ALIAS ST_Envelope FOR "geodb.GeoDB.ST_Envelope" -CREATE ALIAS ST_Equals FOR "geodb.GeoDB.ST_Equals" -CREATE ALIAS ST_GeoHash FOR "geodb.GeoDB.ST_GeoHash" -CREATE ALIAS ST_GeomFromEWKB FOR "geodb.GeoDB.ST_GeomFromEWKB" -CREATE ALIAS ST_GeomFromEWKT FOR "geodb.GeoDB.ST_GeomFromEWKT" -CREATE ALIAS ST_GeomFromText FOR "geodb.GeoDB.ST_GeomFromText" -CREATE ALIAS ST_GeomFromWKB FOR "geodb.GeoDB.ST_GeomFromWKB" -CREATE ALIAS ST_Intersection FOR "geodb.GeoDB.ST_Intersection" -CREATE ALIAS ST_Intersects FOR "geodb.GeoDB.ST_Intersects" -CREATE ALIAS ST_IsEmpty FOR "geodb.GeoDB.ST_IsEmpty" -CREATE ALIAS ST_IsSimple FOR "geodb.GeoDB.ST_IsSimple" -CREATE ALIAS ST_IsValid FOR "geodb.GeoDB.ST_IsValid" -CREATE ALIAS ST_MakePoint FOR "geodb.GeoDB.ST_MakePoint" -CREATE ALIAS ST_MakeBox2D FOR "geodb.GeoDB.ST_MakeBox2D" -CREATE ALIAS ST_Overlaps FOR "geodb.GeoDB.ST_Overlaps" -CREATE ALIAS ST_Relate FOR "geodb.GeoDB.ST_Relate" -CREATE ALIAS ST_SRID FOR "geodb.GeoDB.ST_SRID" -CREATE ALIAS ST_X FOR "geodb.GeoDB.ST_X" -CREATE ALIAS ST_Y FOR "geodb.GeoDB.ST_Y" -CREATE ALIAS ST_SetSRID FOR "geodb.GeoDB.ST_SetSRID" -CREATE ALIAS ST_Simplify FOR "geodb.GeoDB.ST_Simplify" -CREATE ALIAS ST_SymDifference FOR "geodb.GeoDB.ST_SymDifference" -CREATE ALIAS ST_Touches FOR "geodb.GeoDB.ST_Touches" -CREATE ALIAS ST_Union FOR "geodb.GeoDB.ST_Union" -CREATE ALIAS ST_Within FOR "geodb.GeoDB.ST_Within" -CREATE ALIAS Version FOR "geodb.GeoDB.Version" -CREATE DOMAIN POINT AS BLOB -CREATE DOMAIN LINESTRING AS BLOB -CREATE DOMAIN POLYGON AS BLOB -CREATE DOMAIN MULTIPOINT AS BLOB -CREATE DOMAIN MULTILINESTRING AS BLOB -CREATE DOMAIN MULTIPOLYGON AS BLOB -CREATE DOMAIN GEOMETRYCOLLECTION AS BLOB -CREATE DOMAIN GEOMETRY AS BLOB -CREATE AGGREGATE ST_Extent FOR "geodb.aggregate.Extent" -CREATE AGGREGATE ST_Union_Aggregate FOR "geodb.aggregate.Union" diff --git a/core/src/main/resources/geodb/geodb_derby.sql b/core/src/main/resources/geodb/geodb_derby.sql new file mode 100644 index 0000000..53f9912 --- /dev/null +++ b/core/src/main/resources/geodb/geodb_derby.sql @@ -0,0 +1,425 @@ +create procedure AddGeometryColumn ( + IN SPATIAL_SCHEMA VARCHAR(128), + IN SPATIAL_TABLE VARCHAR(128), + IN SPATIAL_COLUMN VARCHAR(128), + IN SPATIAL_SRID INT, + IN SPATIAL_TYPE VARCHAR(128), + IN SPATIAL_DIM INT +) + language java + external name 'geodb.GeoDB.AddGeometryColumnProc' + parameter style java + modifies sql data; + +create procedure CreateSpatialIndex ( + IN SPATIAL_SCHEMA VARCHAR(128), + IN SPATIAL_TABLE VARCHAR(128), + IN SPATIAL_COLUMN VARCHAR(128), + IN SPATIAL_SRID VARCHAR(16) +) + language java + external name 'geodb.GeoDB.CreateSpatialIndexProc' + parameter style java + modifies sql data; + +create procedure DropGeometryColumn ( + IN SPATIAL_SCHEMA VARCHAR(128), + IN SPATIAL_TABLE VARCHAR(128), + IN SPATIAL_COLUMN VARCHAR(128) +) + language java + external name 'geodb.GeoDB.DropGeometryColumnProc' + parameter style java + modifies sql data; + +create procedure DropGeometryColumns ( + IN SPATIAL_SCHEMA VARCHAR(128), + IN SPATIAL_TABLE VARCHAR(128) +) + language java + external name 'geodb.GeoDB.DropGeometryColumnsProc' + parameter style java + modifies sql data; + +#CREATE ALIAS DropSpatialIndex for "geodb.GeoDB.DropSpatialIndex" + +create function EnvelopeAsText ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS VARCHAR(32672) + language java + external name 'geodb.GeoDB.EnvelopeAsText' + parameter style java; + +create function GeometryType ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS VARCHAR(32672) + language java + external name 'geodb.GeoDB.GeometryType' + parameter style java; + +create function ST_Area ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS DOUBLE PRECISION + language java + external name 'geodb.GeoDB.ST_Area' + parameter style java; + +create function ST_AsEWKB ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_AsEWKB' + parameter style java; + +create function ST_AsEWKT ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS VARCHAR(32672) + language java + external name 'geodb.GeoDB.ST_AsEWKT' + parameter style java; + +create function ST_AsHexEWKB ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS VARCHAR(32672) + language java + external name 'geodb.GeoDB.ST_AsHexEWKB' + parameter style java; + +create function ST_AsText ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS VARCHAR(32672) + language java + external name 'geodb.GeoDB.ST_AsText' + parameter style java; + +create function ST_BBOX ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_BBox' + parameter style java; + +create function ST_Boundary ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_Boundary' + parameter style java; + +create function ST_Buffer ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA, + SPATIAL_DISTANCE DOUBLE PRECISION +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_Buffer' + parameter style java; + +create function ST_Centroid ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_Centroid' + parameter style java; + +create function ST_Crosses ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_Crosses' + parameter style java; + +create function ST_Contains ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_Contains' + parameter style java; + +create function ST_ConvexHull ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_ConvexHull' + parameter style java; + +create function ST_DWithin ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA, + SPATIAL_DISTANCE DOUBLE PREISION +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_DWithin' + parameter style java; + +create function ST_Disjoint ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_Disjoint' + parameter style java; + +create function ST_Distance ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS DOUBLE PRECISION + language java + external name 'geodb.GeoDB.ST_Distance' + parameter style java; + +create function ST_Difference ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_Difference' + parameter style java; + +create function ST_Dimension ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS INT + language java + external name 'geodb.GeoDB.ST_Dimension' + parameter style java; + +# TODO: Is this the correct return type? +create function ST_Envelope ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS VARCHAR(32672) + language java + external name 'geodb.GeoDB.ST_Envelope' + parameter style java; + +create function ST_Equals ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_Equals' + parameter style java; + +create function ST_GeoHash ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS VARCHAR(32672) + language java + external name 'geodb.GeoDB.ST_GeoHash' + parameter style java; + +create function ST_GeomFromEWKB ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_GeomFromEWKB' + parameter style java; + +create function ST_GeomFromEWKT ( + SPATIAL_WKT VARCHAR(32672) +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_GeomFromEWKT' + parameter style java; + +create function ST_GeomFromText ( + SPATIAL_WKT VARCHAR(32672), + SPATIAL_SRID INTEGER +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_GeomFromText' + parameter style java; + +create function ST_GeomFromWKB ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA, + SPATIAL_SRID INTEGER +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_GeomFromWKB' + parameter style java; + +create function ST_Intersection ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_Intersection' + parameter style java; + +#CREATE ALIAS ST_Intersection FOR "geodb.GeoDB.ST_Intersection" + +create function ST_Intersects ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_Intersects' + parameter style java; + +create function ST_IsEmpty ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_IsEmpty' + parameter style java; + +create function ST_IsSimple ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_IsSimple' + parameter style java; + +create function ST_IsValid ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_IsValid' + parameter style java; + +create function ST_MakePoint ( + SPATIAL_X DOUBLE PRECISION, + SPATIAL_Y DOUBLE PRECISION +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_MakePoint' + parameter style java; + +#CREATE ALIAS ST_MakePoint FOR "geodb.GeoDB.ST_MakePoint" + +create function ST_MakeBox2D ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_MakeBox2D' + parameter style java; + +create function ST_MakeBox2D ( + SPATIAL_X1 DOUBLE PRECISION, + SPATIAL_Y1 DOUBLE PRECISION, + SPATIAL_X2 DOUBLE PRECISION, + SPATIAL_Y2 DOUBLE PRECISION +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_MakeBox2D' + parameter style java; + +create function ST_Overlaps ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_Overlaps' + parameter style java; + +# Derby doesn't support function overloading. +#create function ST_Relate ( +# SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, +# SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA, +# SPATIAL_INTERSECTION_PATTERN VARCHAR(32672) +#) RETURNS BOOLEAN +# language java +# external name 'geodb.GeoDB.ST_Relate' +# parameter style java; + +create function ST_Relate ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS VARCHAR(32672) + language java + external name 'geodb.GeoDB.ST_Relate' + parameter style java; + +create function ST_SRID ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS INT + language java + external name 'geodb.GeoDB.ST_SRID' + parameter style java; + +create function ST_X ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS DOUBLE PRECISION + language java + external name 'geodb.GeoDB.ST_X' + parameter style java; + +create function ST_Y ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS DOUBLE PRECISION + language java + external name 'geodb.GeoDB.ST_Y' + parameter style java; + +create function ST_SetSRID ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA, + SPATIAL_SRID INT +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_SetSRID' + parameter style java; + +create function ST_Simplify ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA, + SPATIAL_DISTANCE DOUBLE PRECISION +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_Simplify' + parameter style java; + +create function ST_SymDifference ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_SymDifference' + parameter style java; + +create function ST_Touches ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_Touches' + parameter style java; + +create function ST_Union ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_Union' + parameter style java; + +create function ST_Within ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS BOOLEAN + language java + external name 'geodb.GeoDB.ST_Within' + parameter style java; + +#CREATE ALIAS Version FOR "geodb.GeoDB.Version" +#CREATE DOMAIN POINT AS BLOB +#CREATE DOMAIN LINESTRING AS BLOB +#CREATE DOMAIN POLYGON AS BLOB +#CREATE DOMAIN MULTIPOINT AS BLOB +#CREATE DOMAIN MULTILINESTRING AS BLOB +#CREATE DOMAIN MULTIPOLYGON AS BLOB +#CREATE DOMAIN GEOMETRYCOLLECTION AS BLOB +#CREATE DOMAIN GEOMETRY AS BLOB + +CREATE DERBY AGGREGATE ST_Extent + FOR VARCHAR(32672) FOR BIT DATA + RETURNS LONG VARCHAR FOR BIT DATA + EXTERNAL NAME 'geodb.aggregate.Extent'; + +#CREATE AGGREGATE ST_Extent FOR "geodb.aggregate.Extent" + +CREATE DERBY AGGREGATE ST_Union_Aggregate + FOR VARCHAR(32672) FOR BIT DATA + RETURNS LONG VARCHAR FOR BIT DATA + EXTERNAL NAME 'geodb.aggregate.Union'; + +#CREATE AGGREGATE ST_Union_Aggregate FOR "geodb.aggregate.Union" diff --git a/core/src/main/resources/geodb/geodb_h2.sql b/core/src/main/resources/geodb/geodb_h2.sql new file mode 100644 index 0000000..522fd53 --- /dev/null +++ b/core/src/main/resources/geodb/geodb_h2.sql @@ -0,0 +1,60 @@ +CREATE ALIAS AddGeometryColumn for "geodb.GeoDB.AddGeometryColumn"; +CREATE ALIAS CreateSpatialIndex for "geodb.GeoDB.CreateSpatialIndex"; +CREATE ALIAS DropGeometryColumn for "geodb.GeoDB.DropGeometryColumn"; +CREATE ALIAS DropGeometryColumns for "geodb.GeoDB.DropGeometryColumns"; +CREATE ALIAS DropSpatialIndex for "geodb.GeoDB.DropSpatialIndex"; +CREATE ALIAS EnvelopeAsText for "geodb.GeoDB.EnvelopeAsText"; +CREATE ALIAS GeometryType for "geodb.GeoDB.GeometryType"; +CREATE ALIAS ST_Area FOR "geodb.GeoDB.ST_Area"; +CREATE ALIAS ST_AsEWKB FOR "geodb.GeoDB.ST_AsEWKB"; +CREATE ALIAS ST_AsEWKT FOR "geodb.GeoDB.ST_AsEWKT"; +CREATE ALIAS ST_AsHexEWKB FOR "geodb.GeoDB.ST_AsHexEWKB"; +CREATE ALIAS ST_AsText FOR "geodb.GeoDB.ST_AsText"; +CREATE ALIAS ST_BBOX FOR "geodb.GeoDB.ST_BBox"; +CREATE ALIAS ST_Boundary FOR "geodb.GeoDB.ST_Boundary"; +CREATE ALIAS ST_Buffer FOR "geodb.GeoDB.ST_Buffer"; +CREATE ALIAS ST_Centroid FOR "geodb.GeoDB.ST_Centroid"; +CREATE ALIAS ST_Crosses FOR "geodb.GeoDB.ST_Crosses"; +CREATE ALIAS ST_Contains FOR "geodb.GeoDB.ST_Contains"; +CREATE ALIAS ST_ConvexHull FOR "geodb.GeoDB.ST_ConvexHull"; +CREATE ALIAS ST_DWithin FOR "geodb.GeoDB.ST_DWithin"; +CREATE ALIAS ST_Disjoint FOR "geodb.GeoDB.ST_Disjoint"; +CREATE ALIAS ST_Distance FOR "geodb.GeoDB.ST_Distance"; +CREATE ALIAS ST_Difference FOR "geodb.GeoDB.ST_Difference"; +CREATE ALIAS ST_Dimension FOR "geodb.GeoDB.ST_Dimension"; +CREATE ALIAS ST_Envelope FOR "geodb.GeoDB.ST_Envelope"; +CREATE ALIAS ST_Equals FOR "geodb.GeoDB.ST_Equals"; +CREATE ALIAS ST_GeoHash FOR "geodb.GeoDB.ST_GeoHash"; +CREATE ALIAS ST_GeomFromEWKB FOR "geodb.GeoDB.ST_GeomFromEWKB"; +CREATE ALIAS ST_GeomFromEWKT FOR "geodb.GeoDB.ST_GeomFromEWKT"; +CREATE ALIAS ST_GeomFromText FOR "geodb.GeoDB.ST_GeomFromText"; +CREATE ALIAS ST_GeomFromWKB FOR "geodb.GeoDB.ST_GeomFromWKB"; +CREATE ALIAS ST_Intersection FOR "geodb.GeoDB.ST_Intersection"; +CREATE ALIAS ST_Intersects FOR "geodb.GeoDB.ST_Intersects"; +CREATE ALIAS ST_IsEmpty FOR "geodb.GeoDB.ST_IsEmpty"; +CREATE ALIAS ST_IsSimple FOR "geodb.GeoDB.ST_IsSimple"; +CREATE ALIAS ST_IsValid FOR "geodb.GeoDB.ST_IsValid"; +CREATE ALIAS ST_MakePoint FOR "geodb.GeoDB.ST_MakePoint"; +CREATE ALIAS ST_MakeBox2D FOR "geodb.GeoDB.ST_MakeBox2D"; +CREATE ALIAS ST_Overlaps FOR "geodb.GeoDB.ST_Overlaps"; +CREATE ALIAS ST_Relate FOR "geodb.GeoDB.ST_Relate"; +CREATE ALIAS ST_SRID FOR "geodb.GeoDB.ST_SRID"; +CREATE ALIAS ST_X FOR "geodb.GeoDB.ST_X"; +CREATE ALIAS ST_Y FOR "geodb.GeoDB.ST_Y"; +CREATE ALIAS ST_SetSRID FOR "geodb.GeoDB.ST_SetSRID"; +CREATE ALIAS ST_Simplify FOR "geodb.GeoDB.ST_Simplify"; +CREATE ALIAS ST_SymDifference FOR "geodb.GeoDB.ST_SymDifference"; +CREATE ALIAS ST_Touches FOR "geodb.GeoDB.ST_Touches"; +CREATE ALIAS ST_Union FOR "geodb.GeoDB.ST_Union"; +CREATE ALIAS ST_Within FOR "geodb.GeoDB.ST_Within"; +CREATE ALIAS Version FOR "geodb.GeoDB.Version"; +CREATE DOMAIN POINT AS BLOB; +CREATE DOMAIN LINESTRING AS BLOB; +CREATE DOMAIN POLYGON AS BLOB; +CREATE DOMAIN MULTIPOINT AS BLOB; +CREATE DOMAIN MULTILINESTRING AS BLOB; +CREATE DOMAIN MULTIPOLYGON AS BLOB; +CREATE DOMAIN GEOMETRYCOLLECTION AS BLOB; +CREATE DOMAIN GEOMETRY AS BLOB; +CREATE AGGREGATE ST_Extent FOR "geodb.aggregate.Extent"; +CREATE AGGREGATE ST_Union_Aggregate FOR "geodb.aggregate.Union"; diff --git a/core/src/test/java/geodb/DatabaseTestUtils.java b/core/src/test/java/geodb/DatabaseTestUtils.java new file mode 100644 index 0000000..2773a25 --- /dev/null +++ b/core/src/test/java/geodb/DatabaseTestUtils.java @@ -0,0 +1,72 @@ +package geodb; + +/** + * Implementations of DatabaseTestUtils provide the + * database-specific implementations of the methods in this interface. + */ +public interface DatabaseTestUtils { + /** + * Creates a new database with the given name. + * + * @param databaseName + * the database name. + * @throws Exception + * if anything goes wrong while creating the new database. + */ + void createDB(String databaseName) throws Exception; + + /** + * Destroys the database with the given name. The name is expected to be + * something like . + * + * @param databaseName + * the database name. + * @throws Exception + * if anything goes wrong while destroying the database. + */ + void destroyDB(String databaseName) throws Exception; + + /** + * Creates a test table with the given name. The ID column should be an + * integer type that is the primary key and have the + * auto-increment capability. + * + * @param tableName + * the table name. + * @param idColumnName + * the ID column name. + * @param geomColumnName + * the optional Geometry column name. + * @returns the CREATE TABLE SQL. + */ + String getCreateTestTableSql(String tableName, String idColumnName, + String geomColumnName); + + /** + * Drops the given table. + * + * @param tableName + * the table name. + * @return the DROP TABLE SQL. + */ + String getDropTableSql(String tableName); + + /** + * Indicates if a DROP TABLE statement drops the table if it + * exists. + * + * @return true if the {@link #dropTable(String)} SQL can be + * run even if the table does not exist. + */ + boolean isDropTableIfExistsSupported(); + + /** + * Creates the SQL to limit the number of results returned by a + * SELECT statement. + * + * @param limit + * the number of rows to fetch. + * @return the LIMIT clause to a SELECT statement. + */ + String getLimitClauseSql(int limit); +} \ No newline at end of file diff --git a/core/src/test/java/geodb/DerbyTestUtils.java b/core/src/test/java/geodb/DerbyTestUtils.java new file mode 100644 index 0000000..8b1448d --- /dev/null +++ b/core/src/test/java/geodb/DerbyTestUtils.java @@ -0,0 +1,72 @@ +package geodb; + +import java.io.File; +import java.sql.DriverManager; + +import org.apache.commons.io.FileUtils; + +/** + * DerbyTestUtils provides the Apache Derby-specific SQL and + * utility methods for unit testing. + */ +public class DerbyTestUtils implements DatabaseTestUtils { + /** + * @see geodb.DatabaseTestUtils#createDB(java.lang.String) + */ + public void createDB(String databaseName) throws Exception { + Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); + DriverManager.getConnection( + "jdbc:derby:directory:target/" + databaseName + ";create=true") + .close(); + } + + /** + * @see geodb.DatabaseTestUtils#destroyDB(java.lang.String) + */ + public void destroyDB(String databaseName) throws Exception { + try { + DriverManager.getConnection( + "jdbc:derby:directory:target/" + databaseName + + ";shutdown=true").close(); + } catch (Exception ignore) { + } + FileUtils.deleteDirectory(new File("target/" + databaseName)); + } + + /** + * @see geodb.DatabaseTestUtils#getCreateTestTableSql(java.lang.String, + * java.lang.String, java.lang.String) + */ + public String getCreateTestTableSql(String tableName, String idColumnName, + String geomColumnName) { + StringBuilder sql = new StringBuilder("CREATE TABLE "); + sql.append(tableName).append(" ("); + sql.append(idColumnName) + .append(" INT NOT NULL GENERATED ALWAYS AS IDENTITY CONSTRAINT ") + .append(tableName.toUpperCase()).append("_PK PRIMARY KEY"); + if (geomColumnName != null) { + sql.append(", ").append(geomColumnName) + .append(" VARCHAR (32672) FOR BIT DATA"); + } + sql.append(')'); + return sql.toString(); + } + + /** + * @see geodb.DatabaseTestUtils#getDropTableSql(java.lang.String) + */ + public String getDropTableSql(String tableName) { + return "DROP TABLE " + tableName; + } + + /** + * @see geodb.DatabaseTestUtils#isDropTableIfExistsSupported() + */ + public boolean isDropTableIfExistsSupported() { + return false; + } + + public String getLimitClauseSql(int limit) { + return "FETCH FIRST " + limit + " ROWS ONLY"; + } +} diff --git a/core/src/test/java/geodb/GeoDBDerbyTest.java b/core/src/test/java/geodb/GeoDBDerbyTest.java new file mode 100644 index 0000000..d9e4a3d --- /dev/null +++ b/core/src/test/java/geodb/GeoDBDerbyTest.java @@ -0,0 +1,50 @@ +package geodb; + +import java.io.File; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; + +import org.apache.commons.io.FileUtils; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; + +/** + * Tests GeoDB with H2. + */ +public class GeoDBDerbyTest extends TestGeoDB { + /** The database connection instance. */ + protected Connection cx; + + /** The Derby test utilities. */ + private static DerbyTestUtils testUtils = new DerbyTestUtils(); + + @Override + protected Connection getConnection() { + return cx; + } + + @Override + protected DatabaseTestUtils getTestUtils() { + return testUtils; + } + + @BeforeClass + public static void createDB() throws Exception { + testUtils.destroyDB(getDatabaseName()); + testUtils.createDB(getDatabaseName()); + } + + @AfterClass + public static void destroyDB() throws Exception { + testUtils.destroyDB(getDatabaseName()); + } + + @Before + public void setUp() throws Exception { + cx = DriverManager.getConnection("jdbc:derby:directory:target/" + getDatabaseName()); + super.setUp(); + } +} diff --git a/core/src/test/java/geodb/GeoDBExtraFunctionsDerbyTest.java b/core/src/test/java/geodb/GeoDBExtraFunctionsDerbyTest.java new file mode 100644 index 0000000..74091b8 --- /dev/null +++ b/core/src/test/java/geodb/GeoDBExtraFunctionsDerbyTest.java @@ -0,0 +1,48 @@ +package geodb; + +import java.sql.Connection; +import java.sql.DriverManager; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; + +/** + * GeoDBExtraFunctionsDerbyTest runs the tests in + * {@link TestGeoDBExtraFunctions} with Derby. + */ +public class GeoDBExtraFunctionsDerbyTest extends TestGeoDBExtraFunctions { + /** The database connection instance. */ + protected Connection cx; + + /** The Derby test utilities. */ + private static DerbyTestUtils testUtils = new DerbyTestUtils(); + + @Override + protected Connection getConnection() { + return cx; + } + + @Override + protected DatabaseTestUtils getTestUtils() { + return testUtils; + } + + @BeforeClass + public static void createDB() throws Exception { + testUtils.destroyDB(getDatabaseName()); + testUtils.createDB(getDatabaseName()); + } + + @AfterClass + public static void destroyDB() throws Exception { + testUtils.destroyDB(getDatabaseName()); + } + + @Before + public void setup() throws Exception { + cx = DriverManager.getConnection("jdbc:derby:directory:target/" + + getDatabaseName()); + super.setup(); + } +} diff --git a/core/src/test/java/geodb/GeoDBExtraFunctionsH2Test.java b/core/src/test/java/geodb/GeoDBExtraFunctionsH2Test.java new file mode 100644 index 0000000..7b8caee --- /dev/null +++ b/core/src/test/java/geodb/GeoDBExtraFunctionsH2Test.java @@ -0,0 +1,64 @@ +package geodb; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.vividsolutions.jts.io.ParseException; + +/** + * GeoDBExtraFunctionsH2Test runs the tests in + * {@link TestGeoDBExtraFunctions} with H2. + */ +public class GeoDBExtraFunctionsH2Test extends TestGeoDBExtraFunctions { + /** The H2 test utilities. */ + private static final H2TestUtils TEST_UTILS = new H2TestUtils(); + + /** The H2 database connection instance. */ + private Connection cx; + + @Override + protected Connection getConnection() { + return cx; + } + + @Override + protected DatabaseTestUtils getTestUtils() { + return TEST_UTILS; + } + + @BeforeClass + @AfterClass + public static void destroyDB() throws Exception { + TEST_UTILS.destroyDB(getDatabaseName()); + } + + @Before + public void setup() throws Exception { + Class.forName("org.h2.Driver"); + cx = DriverManager.getConnection("jdbc:h2:target/" + getDatabaseName()); + super.setup(); + } + + @Test + public void testRelateWithMatrix() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("CALL ST_Relate(ST_GeomFromText('POINT(1 2)',4326), ST_Buffer(ST_GeomFromText('POINT(1 2)',4326),2), '0FFFFFFF2')"); + rs.next(); + boolean result = rs.getBoolean(1); + st.close(); + //I don't really understand this function so not sure if the result is correct. At least the result of both tests seems consistent. + assertTrue(result); + } +} diff --git a/core/src/test/java/geodb/GeoDBFunctionDerbyTest.java b/core/src/test/java/geodb/GeoDBFunctionDerbyTest.java new file mode 100644 index 0000000..045031c --- /dev/null +++ b/core/src/test/java/geodb/GeoDBFunctionDerbyTest.java @@ -0,0 +1,48 @@ +package geodb; + +import java.sql.Connection; +import java.sql.DriverManager; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; + +/** + * GeoDBFunctionDerbyTest runs the tests in + * {@link TestGeoDBFunction} with Derby. + */ +public class GeoDBFunctionDerbyTest extends TestGeoDBFunction { + /** The database connection instance. */ + protected Connection cx; + + /** The Derby test utilities. */ + private static DerbyTestUtils testUtils = new DerbyTestUtils(); + + @Override + protected Connection getConnection() { + return cx; + } + + @Override + protected DatabaseTestUtils getTestUtils() { + return testUtils; + } + + @BeforeClass + public static void createDB() throws Exception { + testUtils.destroyDB(getDatabaseName()); + testUtils.createDB(getDatabaseName()); + } + + @AfterClass + public static void destroyDB() throws Exception { + testUtils.destroyDB(getDatabaseName()); + } + + @Before + public void setUp() throws Exception { + cx = DriverManager.getConnection("jdbc:derby:directory:target/" + + getDatabaseName()); + super.setUp(); + } +} diff --git a/core/src/test/java/geodb/GeoDBFunctionH2Test.java b/core/src/test/java/geodb/GeoDBFunctionH2Test.java new file mode 100644 index 0000000..e258286 --- /dev/null +++ b/core/src/test/java/geodb/GeoDBFunctionH2Test.java @@ -0,0 +1,43 @@ +package geodb; + +import java.sql.Connection; +import java.sql.DriverManager; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; + +/** + * GeoDBFunctionH2Test runs the tests in {@link TestGeoDBFunction} + * with H2. + */ +public class GeoDBFunctionH2Test extends TestGeoDBFunction { + /** The H2 test utilities. */ + private static final H2TestUtils TEST_UTILS = new H2TestUtils(); + + /** The H2 database connection instance. */ + private Connection cx; + + @Override + protected Connection getConnection() { + return cx; + } + + @Override + protected DatabaseTestUtils getTestUtils() { + return TEST_UTILS; + } + + @BeforeClass + @AfterClass + public static void destroyDB() throws Exception { + TEST_UTILS.destroyDB(getDatabaseName()); + } + + @Before + public void setUp() throws Exception { + Class.forName("org.h2.Driver"); + cx = DriverManager.getConnection("jdbc:h2:target/" + getDatabaseName()); + super.setUp(); + } +} diff --git a/core/src/test/java/geodb/GeoDBH2Test.java b/core/src/test/java/geodb/GeoDBH2Test.java new file mode 100644 index 0000000..7a6626f --- /dev/null +++ b/core/src/test/java/geodb/GeoDBH2Test.java @@ -0,0 +1,42 @@ +package geodb; + +import java.sql.Connection; +import java.sql.DriverManager; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; + +/** + * GeoDBH2Test runs the tests in {@link TestGeoDB} with H2. + */ +public class GeoDBH2Test extends TestGeoDB { + /** The H2 test utilities. */ + private static final H2TestUtils TEST_UTILS = new H2TestUtils(); + + /** The H2 database connection instance. */ + private Connection cx; + + @Override + protected Connection getConnection() { + return cx; + } + + @Override + protected DatabaseTestUtils getTestUtils() { + return TEST_UTILS; + } + + @BeforeClass + @AfterClass + public static void destroyDB() throws Exception { + TEST_UTILS.destroyDB(getDatabaseName()); + } + + @Before + public void setUp() throws Exception { + Class.forName("org.h2.Driver"); + cx = DriverManager.getConnection("jdbc:h2:target/" + getDatabaseName()); + super.setUp(); + } +} diff --git a/core/src/test/java/geodb/GeoDBTest.java b/core/src/test/java/geodb/GeoDBTest.java deleted file mode 100644 index c17aa30..0000000 --- a/core/src/test/java/geodb/GeoDBTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package geodb; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.sql.ResultSet; -import java.sql.Statement; - -import org.junit.Before; -import org.junit.Test; - -public class GeoDBTest extends GeoDBTestSupport { - - @Before - public void setUp() throws Exception { - super.setUp(); - - Statement st = cx.createStatement(); - st.execute("DROP TABLE IF EXISTS _GEODB"); - st.execute("DROP TABLE IF EXISTS spatial"); - st.execute("DROP TABLE IF EXISTS spatial_hatbox"); - st.execute("DROP TABLE IF EXISTS noindex"); - st.close(); - } - - @Test - public void testInitDB() throws Exception { - ResultSet tables = cx.getMetaData().getTables(null, null, "_GEODB", new String[] {"TABLE"}); - assertFalse(tables.next()); - - GeoDB.InitGeoDB(cx); - tables = cx.getMetaData().getTables(null, null, "_GEODB", new String[] {"TABLE"}); - assertTrue(tables.next()); - - tables.close(); - } - - @Test - public void testCreateSpatialIndex() throws Exception { - GeoDB.InitGeoDB(cx); - Statement st = cx.createStatement(); - - st.execute("CREATE TABLE spatial (id INT AUTO_INCREMENT PRIMARY KEY, geom BLOB)"); - st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(0 0)', 4326))"); - st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(1 1)', 4326))"); - st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(2 2)', 4326))"); - st.close(); - - ResultSet tables = - cx.getMetaData().getTables(null, null, "SPATIAL_HATBOX", new String[] {"TABLE"}); - assertFalse(tables.next()); - GeoDB.CreateSpatialIndex(cx, null, "SPATIAL", "GEOM", "4326"); - - tables = - cx.getMetaData().getTables(null, null, "SPATIAL_HATBOX", new String[] {"TABLE"}); - assertTrue(tables.next()); - st.close(); - } - - @Test - public void testGetSRID() throws Exception { - Statement st = cx.createStatement(); - st.execute("CREATE TABLE spatial (id INT AUTO_INCREMENT PRIMARY KEY, geom BLOB)"); - st.execute("CALL CreateSpatialIndex(null, 'SPATIAL', 'GEOM', '4326')"); - assertEquals(4326, GeoDB.GetSRID(cx, null, "SPATIAL")); - - st.execute("CREATE TABLE noindex (id INT AUTO_INCREMENT PRIMARY KEY, geom BLOB)"); - assertEquals(-1, GeoDB.GetSRID(cx, null, "NOINDEX")); - - st.close(); - } -} diff --git a/core/src/test/java/geodb/GeoDBTestSupport.java b/core/src/test/java/geodb/GeoDBTestSupport.java index df32488..f044485 100644 --- a/core/src/test/java/geodb/GeoDBTestSupport.java +++ b/core/src/test/java/geodb/GeoDBTestSupport.java @@ -1,32 +1,68 @@ package geodb; import java.sql.Connection; -import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; -import org.h2.tools.DeleteDbFiles; import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; - -public class GeoDBTestSupport { - - protected Connection cx; - - @BeforeClass - @AfterClass - public static void destroyDB() throws Exception { - DeleteDbFiles.execute("target", "geodb", true); + +public abstract class GeoDBTestSupport { + + /** + * Returns the connection to the database under test. + * + * @return the connection instance. + */ + protected abstract Connection getConnection(); + + protected abstract DatabaseTestUtils getTestUtils(); + + /** + * Creates a test table with the given name. The ID column should be an + * integer type that is the primary key and have the + * auto-increment capability. + * + * @param st + * the statement to execute the SQL. + * @param tableName + * the table name. + * @param idColumnName + * the ID column name. + * @param geomColumnName + * the Geometry column name. + * @throws SQLException + * if unable to create the table. + */ + protected void createTable(Statement st, String tableName, + String idColumnName, String geomColumnName) throws SQLException { + String sql = getTestUtils().getCreateTestTableSql(tableName, + idColumnName, geomColumnName); + st.execute(sql); } - - @Before - public void setUp() throws Exception { - Class.forName("org.h2.Driver"); - cx = DriverManager.getConnection("jdbc:h2:target/geodb"); + + /** + * Drops the given table. + * + * @param st + * the statement to execute the SQL. + * @param tableName + * the table name. + * @throws SQLException + * if unable to drop the table. + */ + protected void dropTable(Statement st, String tableName) throws SQLException { + String sql = getTestUtils().getDropTableSql(tableName); + try { + st.execute(sql); + } catch (SQLException e) { + if (getTestUtils().isDropTableIfExistsSupported()) { + throw e; + } + } } - + @After public void tearDown() throws Exception { - cx.close(); + getConnection().close(); } } diff --git a/core/src/test/java/geodb/H2TestUtils.java b/core/src/test/java/geodb/H2TestUtils.java new file mode 100644 index 0000000..592017f --- /dev/null +++ b/core/src/test/java/geodb/H2TestUtils.java @@ -0,0 +1,60 @@ +package geodb; + +import java.sql.DriverManager; + +import org.h2.tools.DeleteDbFiles; + +/** + * H2TestUtils assists in generating H2-specific SQL and utility + * methods for unit testing. + */ +public class H2TestUtils implements DatabaseTestUtils { + /** + * @see geodb.DatabaseTestUtils#createDB(java.lang.String) + */ + public void createDB(String databaseName) throws Exception { + Class.forName("org.h2.Driver"); + DriverManager.getConnection("jdbc:h2:target/" + databaseName).close(); + } + + /** + * @see geodb.DatabaseTestUtils#destroyDB(java.lang.String) + */ + public void destroyDB(String databaseName) throws Exception { + DeleteDbFiles.execute("target", databaseName, true); + } + + /** + * @see geodb.DatabaseTestUtils#getCreateTestTableSql(java.lang.String, + * java.lang.String, java.lang.String) + */ + public String getCreateTestTableSql(String tableName, String idColumnName, + String geomColumnName) { + StringBuilder sql = new StringBuilder("CREATE TABLE "); + sql.append(tableName).append(" (").append(idColumnName) + .append(" INT AUTO_INCREMENT PRIMARY KEY"); + if (geomColumnName != null) { + sql.append(", ").append(geomColumnName).append(" BLOB"); + } + sql.append(')'); + return sql.toString(); + } + + /** + * @see geodb.DatabaseTestUtils#getDropTableSql(java.lang.String) + */ + public String getDropTableSql(String tableName) { + return "DROP TABLE IF EXISTS " + tableName; + } + + /** + * @see geodb.DatabaseTestUtils#isDropTableIfExistsSupported() + */ + public boolean isDropTableIfExistsSupported() { + return true; + } + + public String getLimitClauseSql(int limit) { + return "LIMIT " + limit; + } +} diff --git a/core/src/test/java/geodb/TestGeoDB.java b/core/src/test/java/geodb/TestGeoDB.java new file mode 100644 index 0000000..ad81927 --- /dev/null +++ b/core/src/test/java/geodb/TestGeoDB.java @@ -0,0 +1,83 @@ +package geodb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public abstract class TestGeoDB extends GeoDBTestSupport { + /** + * The name of the database. + * @return the database name. + */ + public static String getDatabaseName() { + return "geodb"; + } + + @Before + public void setUp() throws Exception { + final Connection cx = getConnection(); + Statement st = cx.createStatement(); + String tableName = GeoDB.getGeoDBTableName(cx); + dropTable(st, tableName); + dropTable(st, "spatial"); + dropTable(st, "spatial_hatbox"); + dropTable(st, "noindex"); + st.close(); + } + + @Test + public void testInitDB() throws Exception { + final Connection cx = getConnection(); + ResultSet tables = cx.getMetaData().getTables(null, null, GeoDB.getGeoDBTableName(cx), new String[] {"TABLE"}); + assertFalse(tables.next()); + + GeoDB.InitGeoDB(cx); + tables = cx.getMetaData().getTables(null, null, GeoDB.getGeoDBTableName(cx), new String[] {"TABLE"}); + assertTrue(tables.next()); + + tables.close(); + } + + @Test + public void testCreateSpatialIndex() throws Exception { + GeoDB.InitGeoDB(getConnection()); + Statement st = getConnection().createStatement(); + + createTable(st, "spatial", "id", "geom"); + st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(0 0)', 4326))"); + st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(1 1)', 4326))"); + st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(2 2)', 4326))"); + + ResultSet tables = + getConnection().getMetaData().getTables(null, null, "SPATIAL_HATBOX", new String[] {"TABLE"}); + assertFalse(tables.next()); + st.execute("CALL CreateSpatialIndex(null, 'SPATIAL', 'GEOM', '4326')"); + + tables = + getConnection().getMetaData().getTables(null, null, "SPATIAL_HATBOX", new String[] {"TABLE"}); + assertTrue(tables.next()); + st.close(); + } + + @Test + public void testGetSRID() throws Exception { + Statement st = getConnection().createStatement(); + createTable(st, "spatial", "id", "geom"); + st.execute("CALL CreateSpatialIndex(null, 'SPATIAL', 'GEOM', '4326')"); + assertEquals(4326, GeoDB.GetSRID(getConnection(), null, "SPATIAL")); + + createTable(st, "noindex", "id", "geom"); + assertEquals(-1, GeoDB.GetSRID(getConnection(), null, "NOINDEX")); + + st.close(); + } +} diff --git a/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java b/core/src/test/java/geodb/TestGeoDBExtraFunctions.java similarity index 80% rename from core/src/test/java/geodb/GeoDBExtraFunctionsTest.java rename to core/src/test/java/geodb/TestGeoDBExtraFunctions.java index 60706b3..5fdf5cd 100644 --- a/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java +++ b/core/src/test/java/geodb/TestGeoDBExtraFunctions.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.io.InputStream; +import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -18,16 +19,24 @@ import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKBReader; -public class GeoDBExtraFunctionsTest extends GeoDBTestSupport { +public abstract class TestGeoDBExtraFunctions extends GeoDBTestSupport { + /** + * The name of the test database. + * + * @return the database name. + */ + public static String getDatabaseName() { + return "geodb_extra_functions"; + } @Before public void setup() throws Exception { - super.setUp(); + Connection cx = getConnection(); Statement st = cx.createStatement(); - st.execute("DROP TABLE IF EXISTS _GEODB"); - st.execute("DROP TABLE IF EXISTS spatial"); - st.execute("DROP TABLE IF EXISTS spatial_hatbox"); - st.execute("DROP TABLE IF EXISTS noindex"); + dropTable(st, GeoDB.getGeoDBTableName(cx)); + dropTable(st, "spatial"); + dropTable(st, "spatial_hatbox"); + dropTable(st, "noindex"); st.close(); GeoDB.InitGeoDB(cx); } @@ -36,6 +45,7 @@ public void setup() throws Exception { @Test public void testDimension() throws SQLException, IOException, ParseException { insertThreePoints(); + Connection cx = getConnection(); Statement st = cx.createStatement(); ResultSet rs = st.executeQuery("select st_dimension(geom) from spatial"); rs.next(); @@ -47,6 +57,7 @@ public void testDimension() throws SQLException, IOException, ParseException { @Test public void testBoundary() throws SQLException, IOException, ParseException { insertThreePoints(); + Connection cx = getConnection(); Statement st = cx.createStatement(); ResultSet rs = st.executeQuery("select st_boundary(geom) from spatial"); rs.next(); @@ -58,8 +69,9 @@ public void testBoundary() throws SQLException, IOException, ParseException { @Test public void testRelate() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); Statement st = cx.createStatement(); - ResultSet rs = st.executeQuery("SELECT ST_Relate(ST_GeomFromText('POINT(1 2)',4326), ST_Buffer(ST_GeomFromText('POINT(1 2)',4326),2))"); + ResultSet rs = st.executeQuery("VALUES ST_Relate(ST_GeomFromText('POINT(1 2)',4326), ST_Buffer(ST_GeomFromText('POINT(1 2)',4326),2))"); rs.next(); String result = rs.getString(1); st.close(); @@ -67,20 +79,10 @@ public void testRelate() throws SQLException, IOException, ParseException { assertThat(result, is("0FFFFFFF2")); } - @Test - public void testRelateWithMatrix() throws SQLException, IOException, ParseException { - Statement st = cx.createStatement(); - ResultSet rs = st.executeQuery("SELECT ST_Relate(ST_GeomFromText('POINT(1 2)',4326), ST_Buffer(ST_GeomFromText('POINT(1 2)',4326),2), '0FFFFFFF2')"); - rs.next(); - boolean result = rs.getBoolean(1); - st.close(); - //I don't really understand this function so not sure if the result is correct. At least the result of both tests seems consistent. - assertTrue(result); - } - @Test public void testConvexHull() throws SQLException, IOException, ParseException { insertThreePoints(); + Connection cx = getConnection(); Statement st = cx.createStatement(); ResultSet rs = st.executeQuery("select st_convexhull(geom) from spatial"); rs.next(); @@ -93,8 +95,9 @@ public void testConvexHull() throws SQLException, IOException, ParseException { @Test public void testDifference() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); Statement st = cx.createStatement(); - ResultSet rs = st.executeQuery("select ST_Difference(" + + ResultSet rs = st.executeQuery("VALUES ST_Difference(" + "ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 4326)," + "ST_GeomFromText('POLYGON((5 5, 5 10, 10 10, 10 5, 5 5))', 4326))"); rs.next(); @@ -106,8 +109,9 @@ public void testDifference() throws SQLException, IOException, ParseException { @Test public void testIntersection() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); Statement st = cx.createStatement(); - ResultSet rs = st.executeQuery("select ST_Intersection(" + + ResultSet rs = st.executeQuery("VALUES ST_Intersection(" + "ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 4326)," + "ST_GeomFromText('POLYGON((5 5, 5 10, 10 10, 10 5, 5 5))', 4326))"); rs.next(); @@ -119,8 +123,9 @@ public void testIntersection() throws SQLException, IOException, ParseException @Test public void testSymdifference() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); Statement st = cx.createStatement(); - ResultSet rs = st.executeQuery("select ST_SymDifference(" + + ResultSet rs = st.executeQuery("VALUES ST_SymDifference(" + "ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 4326)," + "ST_GeomFromText('POLYGON((5 5, 5 15, 10 15, 10 5, 5 5))', 4326))"); rs.next(); @@ -133,8 +138,9 @@ public void testSymdifference() throws SQLException, IOException, ParseException @Test public void testUnion() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); Statement st = cx.createStatement(); - ResultSet rs = st.executeQuery("select ST_Union(" + + ResultSet rs = st.executeQuery("VALUES ST_Union(" + "ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 4326)," + "ST_GeomFromText('POLYGON((5 5, 5 15, 10 15, 10 5, 5 5))', 4326))"); rs.next(); @@ -145,14 +151,12 @@ public void testUnion() throws SQLException, IOException, ParseException { } private void insertThreePoints() throws SQLException{ + Connection cx = getConnection(); Statement st = cx.createStatement(); - st.execute("CREATE TABLE spatial (id INT AUTO_INCREMENT PRIMARY KEY, geom BLOB)"); + createTable(st, "spatial", "id", "geom"); st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(0 0)', 4326))"); st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(1 1)', 4326))"); st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(2 2)', 4326))"); st.close(); } - - - } diff --git a/core/src/test/java/geodb/GeoDBFunctionTest.java b/core/src/test/java/geodb/TestGeoDBFunction.java similarity index 83% rename from core/src/test/java/geodb/GeoDBFunctionTest.java rename to core/src/test/java/geodb/TestGeoDBFunction.java index d398c78..72f12b3 100644 --- a/core/src/test/java/geodb/GeoDBFunctionTest.java +++ b/core/src/test/java/geodb/TestGeoDBFunction.java @@ -1,10 +1,8 @@ package geodb; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; +import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -15,20 +13,27 @@ import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.WKTReader; -public class GeoDBFunctionTest extends GeoDBTestSupport { +public abstract class TestGeoDBFunction extends GeoDBTestSupport { + /** + * The name of the test database. + * + * @return the database name. + */ + public static String getDatabaseName() { + return "geodb_function"; + } @Before public void setUp() throws Exception { - super.setUp(); - + Connection cx = getConnection(); GeoDB.InitGeoDB(cx); Statement st = cx.createStatement(); - st.execute("DROP TABLE IF EXISTS spatial"); - st.execute("DROP TABLE IF EXISTS spatial2"); + dropTable(st, "spatial"); + dropTable(st, "spatial2"); st.execute("DELETE FROM geometry_columns"); - - st.execute("CREATE TABLE spatial (id INT AUTO_INCREMENT PRIMARY KEY, geom BLOB)"); + + createTable(st, "spatial", "id", "geom"); st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(0 0)', 4326))"); st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(1 1)', 4326))"); st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(2 2)', 4326))"); @@ -37,8 +42,9 @@ public void setUp() throws Exception { @Test public void testSRID() throws Exception { + Connection cx = getConnection(); Statement st = cx.createStatement(); - ResultSet rs = st.executeQuery("SELECT ST_SRID(geom) FROM spatial LIMIT 1"); + ResultSet rs = st.executeQuery("SELECT ST_SRID(geom) FROM spatial " + getTestUtils().getLimitClauseSql(1)); rs.next(); assertEquals(4326, rs.getInt(1)); @@ -48,6 +54,7 @@ public void testSRID() throws Exception { @Test public void testAddGeometryColumn() throws Exception { + Connection cx = getConnection(); Statement st = cx.createStatement(); st.execute("CALL AddGeometryColumn(NULL,'SPATIAL', 'FOO', -1, 'POINT', 2)"); @@ -74,8 +81,9 @@ public void testAddGeometryColumn() throws Exception { @Test public void testAddGeometryColumn2() throws Exception { + Connection cx = getConnection(); Statement st = cx.createStatement(); - st.execute("CREATE TABLE spatial2 (id INT AUTO_INCREMENT PRIMARY KEY)"); + createTable(st, "spatial2", "id", null); st.execute("CALL AddGeometryColumn(null, 'SPATIAL2', 'GEOM', 4326, 'POINT', 2)"); ResultSet rs = st.executeQuery("SELECT * from geometry_columns"); @@ -98,12 +106,13 @@ public void testAddGeometryColumn2() throws Exception { rs.close(); st.close(); - } + @Test public void testDropGeometryColumn() throws Exception { testAddGeometryColumn(); + Connection cx = getConnection(); Statement st = cx.createStatement(); st.executeQuery("SELECT foo FROM spatial"); @@ -121,6 +130,7 @@ public void testDropGeometryColumn() throws Exception { @Test public void testDropGeometryColumns() throws Exception { + Connection cx = getConnection(); Statement st = cx.createStatement(); st.execute("CALL AddGeometryColumn(NULL,'SPATIAL', 'FOO', -1, 'POINT', 2)"); @@ -152,10 +162,11 @@ public void testDistance() throws Exception { Geometry g2 = wkt.read("POINT(90711.7123 56791.89)"); double dist = g1.distance(g2); + Connection cx = getConnection(); Statement st = cx.createStatement(); ResultSet rs = st.executeQuery( - "CALL ST_Distance(ST_GeomFromText('POINT(12123.343 79586.125)',-1), " + - " ST_GeomFromText('POINT(90711.7123 56791.89)',-1));"); + "VALUES ST_Distance(ST_GeomFromText('POINT(12123.343 79586.125)',-1), " + + " ST_GeomFromText('POINT(90711.7123 56791.89)',-1))"); rs.next(); double result = rs.getDouble(1); assertEquals(dist, result, 0.00001); @@ -164,9 +175,10 @@ public void testDistance() throws Exception { @Test public void testST_X() throws Exception { + Connection cx = getConnection(); Statement st = cx.createStatement(); ResultSet rs = st.executeQuery( - "CALL ST_X(ST_GeomFromText('POINT(12123.343 79586.125)',-1));"); + "VALUES ST_X(ST_GeomFromText('POINT(12123.343 79586.125)',-1))"); rs.next(); double result = rs.getDouble(1); assertEquals(12123.343, result, 0.00001); @@ -174,9 +186,10 @@ public void testST_X() throws Exception { @Test public void testST_Y() throws Exception { + Connection cx = getConnection(); Statement st = cx.createStatement(); ResultSet rs = st.executeQuery( - "CALL ST_Y(ST_GeomFromText('POINT(12123.343 79586.125)',-1));"); + "VALUES ST_Y(ST_GeomFromText('POINT(12123.343 79586.125)',-1))"); rs.next(); double result = rs.getDouble(1); assertEquals(79586.125, result, 0.00001); diff --git a/core/src/test/java/geodb/aggregate/AggregateFunctionDerbyTest.java b/core/src/test/java/geodb/aggregate/AggregateFunctionDerbyTest.java new file mode 100644 index 0000000..05d31e5 --- /dev/null +++ b/core/src/test/java/geodb/aggregate/AggregateFunctionDerbyTest.java @@ -0,0 +1,51 @@ +package geodb.aggregate; + +import geodb.DatabaseTestUtils; +import geodb.DerbyTestUtils; + +import java.sql.Connection; +import java.sql.DriverManager; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; + +/** + * AggregateFunctionDerbyTest runs the tests in + * {@link TestAggregateFunction} with Derby. + */ +public class AggregateFunctionDerbyTest extends TestAggregateFunction { + /** The database connection instance. */ + protected Connection cx; + + /** The Derby test utilities. */ + private static DerbyTestUtils testUtils = new DerbyTestUtils(); + + @Override + protected Connection getConnection() { + return cx; + } + + @Override + protected DatabaseTestUtils getTestUtils() { + return testUtils; + } + + @BeforeClass + public static void createDB() throws Exception { + testUtils.destroyDB(getDatabaseName()); + testUtils.createDB(getDatabaseName()); + } + + @AfterClass + public static void destroyDB() throws Exception { + testUtils.destroyDB(getDatabaseName()); + } + + @Before + public void setup() throws Exception { + cx = DriverManager.getConnection("jdbc:derby:directory:target/" + + getDatabaseName()); + super.setup(); + } +} diff --git a/core/src/test/java/geodb/aggregate/AggregateFunctionH2Test.java b/core/src/test/java/geodb/aggregate/AggregateFunctionH2Test.java new file mode 100644 index 0000000..3feeaf5 --- /dev/null +++ b/core/src/test/java/geodb/aggregate/AggregateFunctionH2Test.java @@ -0,0 +1,47 @@ +package geodb.aggregate; + +import geodb.DatabaseTestUtils; +import geodb.H2TestUtils; +import geodb.TestGeoDBFunction; + +import java.sql.Connection; +import java.sql.DriverManager; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; + +/** + * AggregateFunction runs the tests in {@link TestGeoDBFunction} + * with H2. + */ +public class AggregateFunctionH2Test extends TestAggregateFunction { + /** The H2 test utilities. */ + private static final H2TestUtils TEST_UTILS = new H2TestUtils(); + + /** The H2 database connection instance. */ + private Connection cx; + + @Override + protected Connection getConnection() { + return cx; + } + + @Override + protected DatabaseTestUtils getTestUtils() { + return TEST_UTILS; + } + + @BeforeClass + @AfterClass + public static void destroyDB() throws Exception { + TEST_UTILS.destroyDB(getDatabaseName()); + } + + @Before + public void setup() throws Exception { + Class.forName("org.h2.Driver"); + cx = DriverManager.getConnection("jdbc:h2:target/" + getDatabaseName()); + super.setup(); + } +} diff --git a/core/src/test/java/geodb/aggregate/AggregateFunctionTest.java b/core/src/test/java/geodb/aggregate/TestAggregateFunction.java similarity index 74% rename from core/src/test/java/geodb/aggregate/AggregateFunctionTest.java rename to core/src/test/java/geodb/aggregate/TestAggregateFunction.java index f43ca8c..7488261 100644 --- a/core/src/test/java/geodb/aggregate/AggregateFunctionTest.java +++ b/core/src/test/java/geodb/aggregate/TestAggregateFunction.java @@ -6,6 +6,7 @@ import geodb.GeoDBTestSupport; import java.io.InputStream; +import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; @@ -16,22 +17,29 @@ import com.vividsolutions.jts.io.InputStreamInStream; import com.vividsolutions.jts.io.WKBReader; -public class AggregateFunctionTest extends GeoDBTestSupport { +public abstract class TestAggregateFunction extends GeoDBTestSupport { + /** + * The name of the test database. + * + * @return the database name. + */ + public static String getDatabaseName() { + return "geodb_aggregate_function"; + } @Before public void setup() throws Exception { - super.setUp(); - + Connection cx = getConnection(); Statement st = cx.createStatement(); - st.execute("DROP TABLE IF EXISTS _GEODB"); - st.execute("DROP TABLE IF EXISTS spatial"); - st.execute("DROP TABLE IF EXISTS spatial_hatbox"); - st.execute("DROP TABLE IF EXISTS noindex"); + dropTable(st, GeoDB.getGeoDBTableName(cx)); + dropTable(st, "spatial"); + dropTable(st, "spatial_hatbox"); + dropTable(st, "noindex"); st.close(); GeoDB.InitGeoDB(cx); st = cx.createStatement(); - st.execute("CREATE TABLE spatial (id INT AUTO_INCREMENT PRIMARY KEY, geom BLOB)"); + createTable(st, "spatial", "id", "geom"); st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(0 0)', 4326))"); st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(1 1)', 4326))"); st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(2 2)', 4326))"); @@ -40,6 +48,7 @@ public void setup() throws Exception { @Test public void testExtent() throws Exception { + Connection cx = getConnection(); Statement st = cx.createStatement(); ResultSet rs = st.executeQuery("select st_extent(geom) from spatial"); rs.next(); @@ -51,6 +60,7 @@ public void testExtent() throws Exception { @Test public void testUnion() throws Exception { + Connection cx = getConnection(); Statement st = cx.createStatement(); ResultSet rs = st.executeQuery("select st_union_aggregate(geom) from spatial"); rs.next(); @@ -59,6 +69,4 @@ public void testUnion() throws Exception { st.close(); assertThat(geometry.getArea(), is(0.0)); } - - } diff --git a/pom.xml b/pom.xml index 180f902..6128aa3 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.opengeo geodb-parent pom - 0-SNAPSHOT + 0.9-SNAPSHOT GeoDB From 778a534b217a83ea21f3233673872a9fb96ce1f2 Mon Sep 17 00:00:00 2001 From: Lonny Date: Tue, 4 Mar 2014 21:36:20 -0700 Subject: [PATCH 2/6] Updated the README to add a Quick Start for Derby. --- README.md | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 90f97db..fc626c4 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ # Introducing GeoDB -GeoDB is a spatial extension of [H2](http://h2database.com), the Java SQL database. GeoDB utilizes the [JTS](http://tsusiatsoftware.net/jts/main.html) library as its geometry engine and the [Hatbox](http://hatbox.sourceforge.net) library for spatial indexing support. +GeoDB is a spatial extension of [H2](http://h2database.com) and [Apache Derby](http://db.apache.org/derby), two Java SQL databases. GeoDB utilizes the [JTS](http://tsusiatsoftware.net/jts/main.html) library as its geometry engine and the [Hatbox](http://hatbox.sourceforge.net) library for spatial indexing support. # Quickstart +## H2 * Download [GeoDB](http://ares.boundlessgeo.com/geodb/0.8/geodb-0.8-app.zip) * Unzip the `geodb-0.8-app.zip` file * Update the `PATH` environment variable to include `geodb-0.8/bin` @@ -34,7 +35,42 @@ GeoDB is a spatial extension of [H2](http://h2database.com), the Java SQL databa * Perform a spatial query - @h2> SELECT ST_AsText(geom) FROM spatial WHERE id IN (SELECT CAST(HATBOX_JOIN_ID AS INT) FROM HATBOX_MBR_INTERSECTS_ENV('PUBLIC', 'SPATIAL', -2, 2, -2, 2)); + @h2> SELECT ST_AsText(geom) FROM spatial WHERE id IN (SELECT CAST(HATBOX_JOIN_ID AS INT) FROM HATBOX_MBR_INTERSECTS_ENV('PUBLIC', 'SPATIAL', -2, 2, -2, 2)); + +## Apache Derby +* Download [GeoDB](http://repo.opengeo.org/org/opengeo/geodb), [Hatbox](http://repo.opengeo.org/net/sourceforge/hatbox/hatbox/) and [JTS](http://mvnrepository.com/artifact/com.vividsolutions/jts) +* Update the `CLASSPATH` environment variables to include the three `jar` files +* Download [Apache Derby](http://db.apache.org/derby/derby_downloads.html) 10.10.1.1 or newer +* Unzip the `db-derby-10.10.1.1-bin.zip` file +* Update the `PATH` environment variable to include `db-derby-10.10.1.1-bin/bin` +* Run the @ij@ command: + + ij> connect 'jdbc:derby:foo;create=true'; + +* Initialize the spatial database: + + ij> CREATE PROCEDURE InitGeoDB () language java external name 'geodb.GeoDB.InitGeoDBProc' parameter style java modifies sql data; + ij> CALL InitGeoDB(); + +* Create a spatial table: + + ij> CREATE TABLE spatial (id INT NOT NULL GENERATED ALWAYS AS IDENTITY CONSTRAINT spatial_pk PRIMARY KEY, geom VARCHAR(32672) FOR BIT DATA); + +* Create some spatial data: + + ij> INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(-5 -5)', 4326)); + ij> INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(0 0)', 4326)); + ij> INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(5 5)', 4326)); + + ij> SELECT ST_AsText(ST_Buffer(geom, 10)) as buffer FROM spatial; + +* Create a spatial index + + ij> CALL CreateSpatialIndex(null, 'SPATIAL', 'GEOM', '4326'); + +* Perform a spatial query + + ij> SELECT ST_AsText(geom) FROM spatial s INNER JOIN table(HATBOX.MBR_INTERSECTS_ENV('APP', 'SPATIAL', -2, 2, -2, 2)) i on s.ID = i.HATBOX_JOIN_ID; # License From 52b019849295893901b08bd0c88e3c2391611cc2 Mon Sep 17 00:00:00 2001 From: Lonny Date: Wed, 5 Mar 2014 20:42:16 -0700 Subject: [PATCH 3/6] Renamed the abstract test classes. Added more unit tests. --- README.md | 6 +- core/src/main/java/geodb/GeoDB.java | 8 +- .../geodb/aggregate/GeoAggregateFunction.java | 14 +- core/src/main/resources/geodb/geodb_derby.sql | 38 ++++-- core/src/test/java/geodb/GeoDBDerbyTest.java | 23 +++- .../geodb/GeoDBExtraFunctionsDerbyTest.java | 4 +- .../java/geodb/GeoDBExtraFunctionsH2Test.java | 4 +- ...ions.java => GeoDBExtraFunctionsTest.java} | 126 +++++++++++++++++- .../java/geodb/GeoDBFunctionDerbyTest.java | 4 +- .../test/java/geodb/GeoDBFunctionH2Test.java | 4 +- ...DBFunction.java => GeoDBFunctionTest.java} | 2 +- core/src/test/java/geodb/GeoDBH2Test.java | 20 ++- .../geodb/{TestGeoDB.java => GeoDBTest.java} | 59 ++++++-- .../aggregate/AggregateFunctionH2Test.java | 4 +- 14 files changed, 268 insertions(+), 48 deletions(-) rename core/src/test/java/geodb/{TestGeoDBExtraFunctions.java => GeoDBExtraFunctionsTest.java} (59%) rename core/src/test/java/geodb/{TestGeoDBFunction.java => GeoDBFunctionTest.java} (99%) rename core/src/test/java/geodb/{TestGeoDB.java => GeoDBTest.java} (57%) diff --git a/README.md b/README.md index fc626c4..9028638 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ GeoDB is a spatial extension of [H2](http://h2database.com) and [Apache Derby](h * Download [GeoDB](http://ares.boundlessgeo.com/geodb/0.8/geodb-0.8-app.zip) * Unzip the `geodb-0.8-app.zip` file * Update the `PATH` environment variable to include `geodb-0.8/bin` -* Run the @geodb@ command: +* Run the `geodb` command: % geodb foo @@ -39,11 +39,11 @@ GeoDB is a spatial extension of [H2](http://h2database.com) and [Apache Derby](h ## Apache Derby * Download [GeoDB](http://repo.opengeo.org/org/opengeo/geodb), [Hatbox](http://repo.opengeo.org/net/sourceforge/hatbox/hatbox/) and [JTS](http://mvnrepository.com/artifact/com.vividsolutions/jts) -* Update the `CLASSPATH` environment variables to include the three `jar` files +* Update the `CLASSPATH` environment variable to include the three `jar` files * Download [Apache Derby](http://db.apache.org/derby/derby_downloads.html) 10.10.1.1 or newer * Unzip the `db-derby-10.10.1.1-bin.zip` file * Update the `PATH` environment variable to include `db-derby-10.10.1.1-bin/bin` -* Run the @ij@ command: +* Run the `ij` command: ij> connect 'jdbc:derby:foo;create=true'; diff --git a/core/src/main/java/geodb/GeoDB.java b/core/src/main/java/geodb/GeoDB.java index c3954f8..5e6791e 100644 --- a/core/src/main/java/geodb/GeoDB.java +++ b/core/src/main/java/geodb/GeoDB.java @@ -1196,6 +1196,7 @@ public static void CreateSpatialIndexProc( String schemaName, String tableName, final Connection connection = DriverManager.getConnection("jdbc:default:connection"); CreateSpatialIndex(connection, schemaName, tableName, columnName, srid); } + public static void CreateSpatialIndex( Connection cx, String schemaName, String tableName, String columnName, String srid) throws SQLException { HashMap args = new HashMap(); @@ -1243,7 +1244,12 @@ public static void CreateSpatialIndex_GeoHash( Connection cx, String schemaName, st.close(); } } - + + public static void DropSpatialIndexProc( String schemaName, String tableName) throws SQLException { + final Connection connection = DriverManager.getConnection("jdbc:default:connection"); + DropSpatialIndex(connection, schemaName, tableName); + } + public static void DropSpatialIndex( Connection cx, String schemaName, String tableName) throws SQLException { diff --git a/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java b/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java index 3f52456..243d862 100644 --- a/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java +++ b/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java @@ -62,6 +62,11 @@ public final int getType(int[] arg0) throws SQLException { * @see org.apache.derby.agg.Aggregator#init() */ public void init() { + try { + init(null); + } catch (SQLException e) { + throw new IllegalStateException("Failed to initialize the function", e); + } } /** @@ -89,13 +94,4 @@ public void merge(GeoAggregateFunction function) { public byte[] terminate() { return (byte[])getResult(); } - - /** - * @see org.h2.api.AggregateFunction#init(java.sql.Connection) - */ - public void init(Connection arg0) throws SQLException { - // TODO Auto-generated method stub - - } - } \ No newline at end of file diff --git a/core/src/main/resources/geodb/geodb_derby.sql b/core/src/main/resources/geodb/geodb_derby.sql index 53f9912..d876f02 100644 --- a/core/src/main/resources/geodb/geodb_derby.sql +++ b/core/src/main/resources/geodb/geodb_derby.sql @@ -41,8 +41,16 @@ create procedure DropGeometryColumns ( parameter style java modifies sql data; -#CREATE ALIAS DropSpatialIndex for "geodb.GeoDB.DropSpatialIndex" +create procedure DropSpatialIndex ( + IN SPATIAL_SCHEMA VARCHAR(128), + IN SPATIAL_TABLE VARCHAR(128) +) + language java + external name 'geodb.GeoDB.DropSpatialIndexProc' + parameter style java + modifies sql data; +# TODO: JUnit create function EnvelopeAsText ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) @@ -57,6 +65,7 @@ create function GeometryType ( external name 'geodb.GeoDB.GeometryType' parameter style java; +# TODO: JUnit create function ST_Area ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS DOUBLE PRECISION @@ -64,6 +73,7 @@ create function ST_Area ( external name 'geodb.GeoDB.ST_Area' parameter style java; +# TODO: JUnit create function ST_AsEWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA @@ -71,6 +81,7 @@ create function ST_AsEWKB ( external name 'geodb.GeoDB.ST_AsEWKB' parameter style java; +# TODO: JUnit create function ST_AsEWKT ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) @@ -85,6 +96,7 @@ create function ST_AsHexEWKB ( external name 'geodb.GeoDB.ST_AsHexEWKB' parameter style java; +# TODO: JUnit create function ST_AsText ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) @@ -92,7 +104,8 @@ create function ST_AsText ( external name 'geodb.GeoDB.ST_AsText' parameter style java; -create function ST_BBOX ( +# TODO: JUnit +create function ST_BBox ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -115,6 +128,7 @@ create function ST_Buffer ( external name 'geodb.GeoDB.ST_Buffer' parameter style java; +# TODO: JUnit create function ST_Centroid ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA @@ -145,6 +159,7 @@ create function ST_ConvexHull ( external name 'geodb.GeoDB.ST_ConvexHull' parameter style java; +# TODO: JUnit create function ST_DWithin ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA, @@ -185,6 +200,7 @@ create function ST_Dimension ( external name 'geodb.GeoDB.ST_Dimension' parameter style java; +# TODO: JUnit # TODO: Is this the correct return type? create function ST_Envelope ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA @@ -201,6 +217,7 @@ create function ST_Equals ( external name 'geodb.GeoDB.ST_Equals' parameter style java; +# TODO: JUnit create function ST_GeoHash ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) @@ -208,6 +225,7 @@ create function ST_GeoHash ( external name 'geodb.GeoDB.ST_GeoHash' parameter style java; +# TODO: JUnit create function ST_GeomFromEWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA @@ -215,6 +233,7 @@ create function ST_GeomFromEWKB ( external name 'geodb.GeoDB.ST_GeomFromEWKB' parameter style java; +# TODO: JUnit create function ST_GeomFromEWKT ( SPATIAL_WKT VARCHAR(32672) ) RETURNS LONG VARCHAR FOR BIT DATA @@ -230,6 +249,7 @@ create function ST_GeomFromText ( external name 'geodb.GeoDB.ST_GeomFromText' parameter style java; +# TODO: JUnit create function ST_GeomFromWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, SPATIAL_SRID INTEGER @@ -238,6 +258,7 @@ create function ST_GeomFromWKB ( external name 'geodb.GeoDB.ST_GeomFromWKB' parameter style java; +# TODO: JUnit create function ST_Intersection ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA @@ -256,6 +277,7 @@ create function ST_Intersects ( external name 'geodb.GeoDB.ST_Intersects' parameter style java; +# TODO: JUnit create function ST_IsEmpty ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -263,6 +285,7 @@ create function ST_IsEmpty ( external name 'geodb.GeoDB.ST_IsEmpty' parameter style java; +# TODO: JUnit create function ST_IsSimple ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -270,6 +293,7 @@ create function ST_IsSimple ( external name 'geodb.GeoDB.ST_IsSimple' parameter style java; +# TODO: JUnit create function ST_IsValid ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -277,6 +301,7 @@ create function ST_IsValid ( external name 'geodb.GeoDB.ST_IsValid' parameter style java; +# TODO: JUnit create function ST_MakePoint ( SPATIAL_X DOUBLE PRECISION, SPATIAL_Y DOUBLE PRECISION @@ -285,8 +310,7 @@ create function ST_MakePoint ( external name 'geodb.GeoDB.ST_MakePoint' parameter style java; -#CREATE ALIAS ST_MakePoint FOR "geodb.GeoDB.ST_MakePoint" - +# TODO: JUnit create function ST_MakeBox2D ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA @@ -352,6 +376,7 @@ create function ST_Y ( external name 'geodb.GeoDB.ST_Y' parameter style java; +# TODO: JUnit create function ST_SetSRID ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, SPATIAL_SRID INT @@ -360,6 +385,7 @@ create function ST_SetSRID ( external name 'geodb.GeoDB.ST_SetSRID' parameter style java; +# TODO: JUnit create function ST_Simplify ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, SPATIAL_DISTANCE DOUBLE PRECISION @@ -415,11 +441,7 @@ CREATE DERBY AGGREGATE ST_Extent RETURNS LONG VARCHAR FOR BIT DATA EXTERNAL NAME 'geodb.aggregate.Extent'; -#CREATE AGGREGATE ST_Extent FOR "geodb.aggregate.Extent" - CREATE DERBY AGGREGATE ST_Union_Aggregate FOR VARCHAR(32672) FOR BIT DATA RETURNS LONG VARCHAR FOR BIT DATA EXTERNAL NAME 'geodb.aggregate.Union'; - -#CREATE AGGREGATE ST_Union_Aggregate FOR "geodb.aggregate.Union" diff --git a/core/src/test/java/geodb/GeoDBDerbyTest.java b/core/src/test/java/geodb/GeoDBDerbyTest.java index d9e4a3d..d4642c2 100644 --- a/core/src/test/java/geodb/GeoDBDerbyTest.java +++ b/core/src/test/java/geodb/GeoDBDerbyTest.java @@ -1,20 +1,19 @@ package geodb; -import java.io.File; import java.sql.Connection; import java.sql.DriverManager; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import org.apache.commons.io.FileUtils; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; /** - * Tests GeoDB with H2. + * GeoDBDerbyTest runs the tests in {@link GeoDBTest} with Derby. */ -public class GeoDBDerbyTest extends TestGeoDB { +public class GeoDBDerbyTest extends GeoDBTest { /** The database connection instance. */ protected Connection cx; @@ -31,6 +30,22 @@ protected DatabaseTestUtils getTestUtils() { return testUtils; } + @Override + protected void createInitGeoDBProcedure(Statement st) throws SQLException { + // Ensure that the procedure does not already exist. + ResultSet rs = st.executeQuery("SELECT * FROM SYS.SYSALIASES a " + + "INNER JOIN SYS.SYSSCHEMAS s " + + "ON s.SCHEMANAME = CURRENT SCHEMA " + + "AND a.ALIAS = 'INITGEODB'"); + boolean procedureExists = rs.next(); + rs.close(); + if (!procedureExists) { + st.execute("CREATE PROCEDURE InitGeoDB () " + + "language java external name 'geodb.GeoDB.InitGeoDBProc' " + + "parameter style java modifies sql data"); + } + } + @BeforeClass public static void createDB() throws Exception { testUtils.destroyDB(getDatabaseName()); diff --git a/core/src/test/java/geodb/GeoDBExtraFunctionsDerbyTest.java b/core/src/test/java/geodb/GeoDBExtraFunctionsDerbyTest.java index 74091b8..78b4bc6 100644 --- a/core/src/test/java/geodb/GeoDBExtraFunctionsDerbyTest.java +++ b/core/src/test/java/geodb/GeoDBExtraFunctionsDerbyTest.java @@ -9,9 +9,9 @@ /** * GeoDBExtraFunctionsDerbyTest runs the tests in - * {@link TestGeoDBExtraFunctions} with Derby. + * {@link GeoDBExtraFunctionsTest} with Derby. */ -public class GeoDBExtraFunctionsDerbyTest extends TestGeoDBExtraFunctions { +public class GeoDBExtraFunctionsDerbyTest extends GeoDBExtraFunctionsTest { /** The database connection instance. */ protected Connection cx; diff --git a/core/src/test/java/geodb/GeoDBExtraFunctionsH2Test.java b/core/src/test/java/geodb/GeoDBExtraFunctionsH2Test.java index 7b8caee..fbe6bcc 100644 --- a/core/src/test/java/geodb/GeoDBExtraFunctionsH2Test.java +++ b/core/src/test/java/geodb/GeoDBExtraFunctionsH2Test.java @@ -18,9 +18,9 @@ /** * GeoDBExtraFunctionsH2Test runs the tests in - * {@link TestGeoDBExtraFunctions} with H2. + * {@link GeoDBExtraFunctionsTest} with H2. */ -public class GeoDBExtraFunctionsH2Test extends TestGeoDBExtraFunctions { +public class GeoDBExtraFunctionsH2Test extends GeoDBExtraFunctionsTest { /** The H2 test utilities. */ private static final H2TestUtils TEST_UTILS = new H2TestUtils(); diff --git a/core/src/test/java/geodb/TestGeoDBExtraFunctions.java b/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java similarity index 59% rename from core/src/test/java/geodb/TestGeoDBExtraFunctions.java rename to core/src/test/java/geodb/GeoDBExtraFunctionsTest.java index 5fdf5cd..94b918c 100644 --- a/core/src/test/java/geodb/TestGeoDBExtraFunctions.java +++ b/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java @@ -3,6 +3,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; import java.io.IOException; import java.io.InputStream; @@ -19,7 +20,7 @@ import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKBReader; -public abstract class TestGeoDBExtraFunctions extends GeoDBTestSupport { +public abstract class GeoDBExtraFunctionsTest extends GeoDBTestSupport { /** * The name of the test database. * @@ -92,7 +93,6 @@ public void testConvexHull() throws SQLException, IOException, ParseException { assertThat(geometry.getArea(), is(0.0)); } - @Test public void testDifference() throws SQLException, IOException, ParseException { Connection cx = getConnection(); @@ -159,4 +159,126 @@ private void insertThreePoints() throws SQLException{ st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(2 2)', 4326))"); st.close(); } + + @Test + public void testContains() throws SQLException, IOException, ParseException { + testBooleanPredicate("ST_Contains", + "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", + "POINT(5 5)", + "POINT(15 15)"); + } + + @Test + public void testCrosses() throws SQLException, IOException, ParseException { + testBooleanPredicate("ST_Crosses", + "LINESTRING(0 -2, 0 2)", + "LINESTRING(-2 0, 2 0)", + "POINT(1 1)"); + } + + @Test + public void testDisjoint() throws SQLException, IOException, ParseException { + testBooleanPredicate("ST_Disjoint", + "POINT(0 0)", + "LINESTRING ( 2 0, 0 2 )", + "LINESTRING ( 0 0, 0 2 )"); + } + + @Test + public void testEquals() throws SQLException, IOException, ParseException { + testBooleanPredicate("ST_Equals", + "LINESTRING(0 0, 10 10)", + "LINESTRING(0 0, 5 5, 10 10)", + "LINESTRING(0 0, 5 5, 11 11)"); + } + + @Test + public void testIntersects() throws SQLException, IOException, ParseException { + testBooleanPredicate("ST_Intersects", + "POINT(0 0)", + "LINESTRING ( 0 0, 0 2 )", + "LINESTRING ( 2 0, 0 2 )"); + } + + @Test + public void testOverlaps() throws SQLException, IOException, ParseException { + testBooleanPredicate("ST_Overlaps", + "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", + "POLYGON((1 1, 1 11, 11 11, 11 1, 1 1))", + "POLYGON((1 1, 1 9, 9 9, 9 1, 1 1))"); + } + + @Test + public void testTouches() throws SQLException, IOException, ParseException { + testBooleanPredicate("ST_Touches", + "LINESTRING(0 0, 1 1, 0 2)", + "POINT(0 2)", + "POINT(1 1)"); + } + + @Test + public void testWithin() throws SQLException, IOException, ParseException { + testBooleanPredicate("ST_Within", + "POLYGON((1 1, 1 9, 9 9, 9 1, 1 1))", + "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", + "POLYGON((2 2, 1 11, 11 11, 11 1, 2 2))"); + } + + /** + * Tests a predicate that takes two geometries as arguments and returns a + * boolean value. + * + * @param predicate + * the predicate to test. + * @param wktA + * the WKT of the first geometry. + * @param wktBPass + * the WKT of the second geometry that should pass. + * @param wktBFail + * the WKT of the second geometry that should fail. + * @throws SQLException + * if unable to run the test in the database. + */ + private void testBooleanPredicate(final String predicate, + final String wktA, final String wktBPass, final String wktBFail) + throws SQLException { + Connection cx = getConnection(); + Statement st = cx.createStatement(); + + // Test the passing condition. + ResultSet rs = st.executeQuery("VALUES " + predicate + "(" + + "ST_GeomFromText('" + wktA + "', 4326)," + + "ST_GeomFromText('" + wktBPass + "', 4326))"); + rs.next(); + boolean result = rs.getBoolean(1); + rs.close(); + assertTrue(result); + + // Test the failing condition. + rs = st.executeQuery("VALUES " + predicate + "(" + "ST_GeomFromText('" + + wktA + "', 4326)," + "ST_GeomFromText('" + wktBFail + + "', 4326))"); + rs.next(); + result = rs.getBoolean(1); + rs.close(); + assertFalse(result); + + // Test the first null. + rs = st.executeQuery("VALUES " + predicate + "(null," + "ST_GeomFromText('" + wktBFail + + "', 4326))"); + rs.next(); + result = rs.getBoolean(1); + rs.close(); + assertFalse(result); + + // Test the second null. + rs = st.executeQuery("VALUES " + predicate + "(" + "ST_GeomFromText('" + + wktA + "', 4326), null)"); + rs.next(); + result = rs.getBoolean(1); + rs.close(); + assertFalse(result); + + st.close(); + } } diff --git a/core/src/test/java/geodb/GeoDBFunctionDerbyTest.java b/core/src/test/java/geodb/GeoDBFunctionDerbyTest.java index 045031c..6aac7b7 100644 --- a/core/src/test/java/geodb/GeoDBFunctionDerbyTest.java +++ b/core/src/test/java/geodb/GeoDBFunctionDerbyTest.java @@ -9,9 +9,9 @@ /** * GeoDBFunctionDerbyTest runs the tests in - * {@link TestGeoDBFunction} with Derby. + * {@link GeoDBFunctionTest} with Derby. */ -public class GeoDBFunctionDerbyTest extends TestGeoDBFunction { +public class GeoDBFunctionDerbyTest extends GeoDBFunctionTest { /** The database connection instance. */ protected Connection cx; diff --git a/core/src/test/java/geodb/GeoDBFunctionH2Test.java b/core/src/test/java/geodb/GeoDBFunctionH2Test.java index e258286..7b0ee5d 100644 --- a/core/src/test/java/geodb/GeoDBFunctionH2Test.java +++ b/core/src/test/java/geodb/GeoDBFunctionH2Test.java @@ -8,10 +8,10 @@ import org.junit.BeforeClass; /** - * GeoDBFunctionH2Test runs the tests in {@link TestGeoDBFunction} + * GeoDBFunctionH2Test runs the tests in {@link GeoDBFunctionTest} * with H2. */ -public class GeoDBFunctionH2Test extends TestGeoDBFunction { +public class GeoDBFunctionH2Test extends GeoDBFunctionTest { /** The H2 test utilities. */ private static final H2TestUtils TEST_UTILS = new H2TestUtils(); diff --git a/core/src/test/java/geodb/TestGeoDBFunction.java b/core/src/test/java/geodb/GeoDBFunctionTest.java similarity index 99% rename from core/src/test/java/geodb/TestGeoDBFunction.java rename to core/src/test/java/geodb/GeoDBFunctionTest.java index 72f12b3..5f077d9 100644 --- a/core/src/test/java/geodb/TestGeoDBFunction.java +++ b/core/src/test/java/geodb/GeoDBFunctionTest.java @@ -13,7 +13,7 @@ import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.WKTReader; -public abstract class TestGeoDBFunction extends GeoDBTestSupport { +public abstract class GeoDBFunctionTest extends GeoDBTestSupport { /** * The name of the test database. * diff --git a/core/src/test/java/geodb/GeoDBH2Test.java b/core/src/test/java/geodb/GeoDBH2Test.java index 7a6626f..739624c 100644 --- a/core/src/test/java/geodb/GeoDBH2Test.java +++ b/core/src/test/java/geodb/GeoDBH2Test.java @@ -2,15 +2,18 @@ import java.sql.Connection; import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; /** - * GeoDBH2Test runs the tests in {@link TestGeoDB} with H2. + * GeoDBH2Test runs the tests in {@link GeoDBTest} with H2. */ -public class GeoDBH2Test extends TestGeoDB { +public class GeoDBH2Test extends GeoDBTest { /** The H2 test utilities. */ private static final H2TestUtils TEST_UTILS = new H2TestUtils(); @@ -27,6 +30,19 @@ protected DatabaseTestUtils getTestUtils() { return TEST_UTILS; } + @Override + protected void createInitGeoDBProcedure(Statement st) throws SQLException { + ResultSet rs = st + .executeQuery("SELECT * FROM INFORMATION_SCHEMA.FUNCTION_ALIASES " + + "WHERE alias_schema IN (schema(), 'PUBLIC') " + + "AND alias_name = 'INITGEODB'"); + boolean functionExists = rs.next(); + rs.close(); + if (!functionExists) { + st.execute("CREATE ALIAS InitGeoDB for \"geodb.GeoDB.InitGeoDB\""); + } + } + @BeforeClass @AfterClass public static void destroyDB() throws Exception { diff --git a/core/src/test/java/geodb/TestGeoDB.java b/core/src/test/java/geodb/GeoDBTest.java similarity index 57% rename from core/src/test/java/geodb/TestGeoDB.java rename to core/src/test/java/geodb/GeoDBTest.java index ad81927..4e67635 100644 --- a/core/src/test/java/geodb/TestGeoDB.java +++ b/core/src/test/java/geodb/GeoDBTest.java @@ -13,7 +13,7 @@ import org.junit.Before; import org.junit.Test; -public abstract class TestGeoDB extends GeoDBTestSupport { +public abstract class GeoDBTest extends GeoDBTestSupport { /** * The name of the database. * @return the database name. @@ -22,6 +22,16 @@ public static String getDatabaseName() { return "geodb"; } + /** + * Creates the InitGeoDB procedure. + * + * @param st + * the statement to execute the SQL. + * @throws SQLException + * if unable to execute the SQL. + */ + protected abstract void createInitGeoDBProcedure(Statement st) throws SQLException; + @Before public void setUp() throws Exception { final Connection cx = getConnection(); @@ -39,18 +49,24 @@ public void testInitDB() throws Exception { final Connection cx = getConnection(); ResultSet tables = cx.getMetaData().getTables(null, null, GeoDB.getGeoDBTableName(cx), new String[] {"TABLE"}); assertFalse(tables.next()); - - GeoDB.InitGeoDB(cx); + + Statement st = cx.createStatement(); + createInitGeoDBProcedure(st); + st.execute("CALL InitGeoDB()"); + st.close(); tables = cx.getMetaData().getTables(null, null, GeoDB.getGeoDBTableName(cx), new String[] {"TABLE"}); assertTrue(tables.next()); tables.close(); } - + @Test public void testCreateSpatialIndex() throws Exception { - GeoDB.InitGeoDB(getConnection()); - Statement st = getConnection().createStatement(); + final Connection cx = getConnection(); + Statement st = cx.createStatement(); + + createInitGeoDBProcedure(st); + st.execute("CALL InitGeoDB()"); createTable(st, "spatial", "id", "geom"); st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(0 0)', 4326))"); @@ -58,13 +74,40 @@ public void testCreateSpatialIndex() throws Exception { st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(2 2)', 4326))"); ResultSet tables = - getConnection().getMetaData().getTables(null, null, "SPATIAL_HATBOX", new String[] {"TABLE"}); + cx.getMetaData().getTables(null, null, "SPATIAL_HATBOX", new String[] {"TABLE"}); + assertFalse(tables.next()); + st.execute("CALL CreateSpatialIndex(null, 'SPATIAL', 'GEOM', '4326')"); + + tables = + cx.getMetaData().getTables(null, null, "SPATIAL_HATBOX", new String[] {"TABLE"}); + assertTrue(tables.next()); + st.close(); + } + + @Test + public void testDropSpatialIndex() throws Exception { + final Connection cx = getConnection(); + Statement st = cx.createStatement(); + + createInitGeoDBProcedure(st); + st.execute("CALL InitGeoDB()"); + + createTable(st, "spatial", "id", "geom"); + + ResultSet tables = + cx.getMetaData().getTables(null, null, "SPATIAL_HATBOX", new String[] {"TABLE"}); assertFalse(tables.next()); st.execute("CALL CreateSpatialIndex(null, 'SPATIAL', 'GEOM', '4326')"); tables = - getConnection().getMetaData().getTables(null, null, "SPATIAL_HATBOX", new String[] {"TABLE"}); + cx.getMetaData().getTables(null, null, "SPATIAL_HATBOX", new String[] {"TABLE"}); assertTrue(tables.next()); + + st.execute("CALL DropSpatialIndex(null, 'SPATIAL')"); + tables = + cx.getMetaData().getTables(null, null, "SPATIAL_HATBOX", new String[] {"TABLE"}); + assertFalse(tables.next()); + st.close(); } diff --git a/core/src/test/java/geodb/aggregate/AggregateFunctionH2Test.java b/core/src/test/java/geodb/aggregate/AggregateFunctionH2Test.java index 3feeaf5..2ea75c0 100644 --- a/core/src/test/java/geodb/aggregate/AggregateFunctionH2Test.java +++ b/core/src/test/java/geodb/aggregate/AggregateFunctionH2Test.java @@ -2,7 +2,7 @@ import geodb.DatabaseTestUtils; import geodb.H2TestUtils; -import geodb.TestGeoDBFunction; +import geodb.GeoDBFunctionTest; import java.sql.Connection; import java.sql.DriverManager; @@ -12,7 +12,7 @@ import org.junit.BeforeClass; /** - * AggregateFunction runs the tests in {@link TestGeoDBFunction} + * AggregateFunction runs the tests in {@link GeoDBFunctionTest} * with H2. */ public class AggregateFunctionH2Test extends TestAggregateFunction { From f8e6f75b7de5b488878550482691cd76d9048401 Mon Sep 17 00:00:00 2001 From: Lonny Date: Thu, 6 Mar 2014 09:04:19 -0700 Subject: [PATCH 4/6] Added more unit tests. Fixed a couple bugs. Added ST_AsBinary. --- core/src/main/java/geodb/GeoDB.java | 19 +- core/src/main/resources/geodb/geodb_derby.sql | 129 ++++---- core/src/main/resources/geodb/geodb_h2.sql | 1 + .../java/geodb/GeoDBExtraFunctionsTest.java | 283 +++++++++++++++++- 4 files changed, 358 insertions(+), 74 deletions(-) diff --git a/core/src/main/java/geodb/GeoDB.java b/core/src/main/java/geodb/GeoDB.java index 5e6791e..f2d6275 100644 --- a/core/src/main/java/geodb/GeoDB.java +++ b/core/src/main/java/geodb/GeoDB.java @@ -446,9 +446,20 @@ public static String ST_AsEWKT( byte[] wkb ) { Geometry g = gFromWKB(wkb); return gToEWKT(g); } - + /** - * Return the Well-Known Binary (WKB) representation of the geometry with SRID meta data. + * Return the Well-Known Binary (WKB) representation of the geometry without SRID meta data. + */ + public static byte[] ST_AsBinary( byte[] wkb ) { + if (wkb == null) { + return null; + } + + return wkb; + } + + /** + * Return the Extended Well-Known Binary (WKB) representation of the geometry with SRID meta data. */ public static byte[] ST_AsEWKB( byte[] wkb ) { return wkb; @@ -488,6 +499,10 @@ public static String ST_GeoHash( byte[] wkb ) { * Return a specified ST_Geometry value from Extended Well-Known Binary representation (EWKB). */ public static byte[] ST_GeomFromEWKB (byte[] wkb) { + if (wkb == null) { + return null; + } + return gToWKB(gFromWKB(wkb)); } diff --git a/core/src/main/resources/geodb/geodb_derby.sql b/core/src/main/resources/geodb/geodb_derby.sql index d876f02..b33556f 100644 --- a/core/src/main/resources/geodb/geodb_derby.sql +++ b/core/src/main/resources/geodb/geodb_derby.sql @@ -50,62 +50,63 @@ create procedure DropSpatialIndex ( parameter style java modifies sql data; -# TODO: JUnit -create function EnvelopeAsText ( +CREATE FUNCTION EnvelopeAsText ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) language java external name 'geodb.GeoDB.EnvelopeAsText' parameter style java; -create function GeometryType ( +CREATE FUNCTION GeometryType ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) language java external name 'geodb.GeoDB.GeometryType' parameter style java; -# TODO: JUnit -create function ST_Area ( +CREATE FUNCTION ST_Area ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS DOUBLE PRECISION language java external name 'geodb.GeoDB.ST_Area' parameter style java; -# TODO: JUnit -create function ST_AsEWKB ( +CREATE FUNCTION ST_AsEWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_AsEWKB' parameter style java; -# TODO: JUnit -create function ST_AsEWKT ( +CREATE FUNCTION ST_AsEWKT ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) language java external name 'geodb.GeoDB.ST_AsEWKT' parameter style java; -create function ST_AsHexEWKB ( +CREATE FUNCTION ST_AsHexEWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) language java external name 'geodb.GeoDB.ST_AsHexEWKB' parameter style java; -# TODO: JUnit -create function ST_AsText ( +CREATE FUNCTION ST_AsText ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) language java external name 'geodb.GeoDB.ST_AsText' parameter style java; -# TODO: JUnit -create function ST_BBox ( +CREATE FUNCTION ST_AsBinary ( + SPATIAL_WKB LONG VARCHAR FOR BIT DATA +) RETURNS LONG VARCHAR FOR BIT DATA + language java + external name 'geodb.GeoDB.ST_AsBinary' + parameter style java; + +CREATE FUNCTION ST_BBox ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -113,14 +114,14 @@ create function ST_BBox ( external name 'geodb.GeoDB.ST_BBox' parameter style java; -create function ST_Boundary ( +CREATE FUNCTION ST_Boundary ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_Boundary' parameter style java; -create function ST_Buffer ( +CREATE FUNCTION ST_Buffer ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, SPATIAL_DISTANCE DOUBLE PRECISION ) RETURNS LONG VARCHAR FOR BIT DATA @@ -128,15 +129,14 @@ create function ST_Buffer ( external name 'geodb.GeoDB.ST_Buffer' parameter style java; -# TODO: JUnit -create function ST_Centroid ( +CREATE FUNCTION ST_Centroid ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_Centroid' parameter style java; -create function ST_Crosses ( +CREATE FUNCTION ST_Crosses ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -144,7 +144,7 @@ create function ST_Crosses ( external name 'geodb.GeoDB.ST_Crosses' parameter style java; -create function ST_Contains ( +CREATE FUNCTION ST_Contains ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -152,24 +152,23 @@ create function ST_Contains ( external name 'geodb.GeoDB.ST_Contains' parameter style java; -create function ST_ConvexHull ( +CREATE FUNCTION ST_ConvexHull ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_ConvexHull' parameter style java; -# TODO: JUnit -create function ST_DWithin ( +CREATE FUNCTION ST_DWithin ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA, - SPATIAL_DISTANCE DOUBLE PREISION + SPATIAL_DISTANCE DOUBLE PRECISION ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_DWithin' parameter style java; -create function ST_Disjoint ( +CREATE FUNCTION ST_Disjoint ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -177,7 +176,7 @@ create function ST_Disjoint ( external name 'geodb.GeoDB.ST_Disjoint' parameter style java; -create function ST_Distance ( +CREATE FUNCTION ST_Distance ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS DOUBLE PRECISION @@ -185,7 +184,7 @@ create function ST_Distance ( external name 'geodb.GeoDB.ST_Distance' parameter style java; -create function ST_Difference ( +CREATE FUNCTION ST_Difference ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA @@ -193,23 +192,22 @@ create function ST_Difference ( external name 'geodb.GeoDB.ST_Difference' parameter style java; -create function ST_Dimension ( +CREATE FUNCTION ST_Dimension ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS INT language java external name 'geodb.GeoDB.ST_Dimension' parameter style java; -# TODO: JUnit # TODO: Is this the correct return type? -create function ST_Envelope ( +CREATE FUNCTION ST_Envelope ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) language java external name 'geodb.GeoDB.ST_Envelope' parameter style java; -create function ST_Equals ( +CREATE FUNCTION ST_Equals ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -217,31 +215,28 @@ create function ST_Equals ( external name 'geodb.GeoDB.ST_Equals' parameter style java; -# TODO: JUnit -create function ST_GeoHash ( +CREATE FUNCTION ST_GeoHash ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) language java external name 'geodb.GeoDB.ST_GeoHash' parameter style java; -# TODO: JUnit -create function ST_GeomFromEWKB ( +CREATE FUNCTION ST_GeomFromEWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_GeomFromEWKB' parameter style java; -# TODO: JUnit -create function ST_GeomFromEWKT ( +CREATE FUNCTION ST_GeomFromEWKT ( SPATIAL_WKT VARCHAR(32672) ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_GeomFromEWKT' parameter style java; -create function ST_GeomFromText ( +CREATE FUNCTION ST_GeomFromText ( SPATIAL_WKT VARCHAR(32672), SPATIAL_SRID INTEGER ) RETURNS LONG VARCHAR FOR BIT DATA @@ -249,8 +244,7 @@ create function ST_GeomFromText ( external name 'geodb.GeoDB.ST_GeomFromText' parameter style java; -# TODO: JUnit -create function ST_GeomFromWKB ( +CREATE FUNCTION ST_GeomFromWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, SPATIAL_SRID INTEGER ) RETURNS LONG VARCHAR FOR BIT DATA @@ -258,8 +252,7 @@ create function ST_GeomFromWKB ( external name 'geodb.GeoDB.ST_GeomFromWKB' parameter style java; -# TODO: JUnit -create function ST_Intersection ( +CREATE FUNCTION ST_Intersection ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA @@ -269,7 +262,7 @@ create function ST_Intersection ( #CREATE ALIAS ST_Intersection FOR "geodb.GeoDB.ST_Intersection" -create function ST_Intersects ( +CREATE FUNCTION ST_Intersects ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -277,32 +270,28 @@ create function ST_Intersects ( external name 'geodb.GeoDB.ST_Intersects' parameter style java; -# TODO: JUnit -create function ST_IsEmpty ( +CREATE FUNCTION ST_IsEmpty ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_IsEmpty' parameter style java; -# TODO: JUnit -create function ST_IsSimple ( +CREATE FUNCTION ST_IsSimple ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_IsSimple' parameter style java; -# TODO: JUnit -create function ST_IsValid ( +CREATE FUNCTION ST_IsValid ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_IsValid' parameter style java; -# TODO: JUnit -create function ST_MakePoint ( +CREATE FUNCTION ST_MakePoint ( SPATIAL_X DOUBLE PRECISION, SPATIAL_Y DOUBLE PRECISION ) RETURNS LONG VARCHAR FOR BIT DATA @@ -310,8 +299,7 @@ create function ST_MakePoint ( external name 'geodb.GeoDB.ST_MakePoint' parameter style java; -# TODO: JUnit -create function ST_MakeBox2D ( +CREATE FUNCTION ST_MakeBox2D ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA @@ -319,7 +307,7 @@ create function ST_MakeBox2D ( external name 'geodb.GeoDB.ST_MakeBox2D' parameter style java; -create function ST_MakeBox2D ( +CREATE FUNCTION ST_MakeBox2D ( SPATIAL_X1 DOUBLE PRECISION, SPATIAL_Y1 DOUBLE PRECISION, SPATIAL_X2 DOUBLE PRECISION, @@ -329,7 +317,7 @@ create function ST_MakeBox2D ( external name 'geodb.GeoDB.ST_MakeBox2D' parameter style java; -create function ST_Overlaps ( +CREATE FUNCTION ST_Overlaps ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -338,7 +326,7 @@ create function ST_Overlaps ( parameter style java; # Derby doesn't support function overloading. -#create function ST_Relate ( +#CREATE FUNCTION ST_Relate ( # SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, # SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA, # SPATIAL_INTERSECTION_PATTERN VARCHAR(32672) @@ -347,7 +335,7 @@ create function ST_Overlaps ( # external name 'geodb.GeoDB.ST_Relate' # parameter style java; -create function ST_Relate ( +CREATE FUNCTION ST_Relate ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) @@ -355,29 +343,28 @@ create function ST_Relate ( external name 'geodb.GeoDB.ST_Relate' parameter style java; -create function ST_SRID ( +CREATE FUNCTION ST_SRID ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS INT language java external name 'geodb.GeoDB.ST_SRID' parameter style java; -create function ST_X ( +CREATE FUNCTION ST_X ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS DOUBLE PRECISION language java external name 'geodb.GeoDB.ST_X' parameter style java; -create function ST_Y ( +CREATE FUNCTION ST_Y ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS DOUBLE PRECISION language java external name 'geodb.GeoDB.ST_Y' parameter style java; -# TODO: JUnit -create function ST_SetSRID ( +CREATE FUNCTION ST_SetSRID ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, SPATIAL_SRID INT ) RETURNS LONG VARCHAR FOR BIT DATA @@ -385,8 +372,7 @@ create function ST_SetSRID ( external name 'geodb.GeoDB.ST_SetSRID' parameter style java; -# TODO: JUnit -create function ST_Simplify ( +CREATE FUNCTION ST_Simplify ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, SPATIAL_DISTANCE DOUBLE PRECISION ) RETURNS LONG VARCHAR FOR BIT DATA @@ -394,7 +380,7 @@ create function ST_Simplify ( external name 'geodb.GeoDB.ST_Simplify' parameter style java; -create function ST_SymDifference ( +CREATE FUNCTION ST_SymDifference ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA @@ -402,7 +388,7 @@ create function ST_SymDifference ( external name 'geodb.GeoDB.ST_SymDifference' parameter style java; -create function ST_Touches ( +CREATE FUNCTION ST_Touches ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -410,7 +396,7 @@ create function ST_Touches ( external name 'geodb.GeoDB.ST_Touches' parameter style java; -create function ST_Union ( +CREATE FUNCTION ST_Union ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA @@ -418,7 +404,7 @@ create function ST_Union ( external name 'geodb.GeoDB.ST_Union' parameter style java; -create function ST_Within ( +CREATE FUNCTION ST_Within ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN @@ -426,7 +412,12 @@ create function ST_Within ( external name 'geodb.GeoDB.ST_Within' parameter style java; -#CREATE ALIAS Version FOR "geodb.GeoDB.Version" +CREATE FUNCTION Version () RETURNS VARCHAR(16) + language java + external name 'geodb.GeoDB.Version' + parameter style java; + +# Derby can't alias types. #CREATE DOMAIN POINT AS BLOB #CREATE DOMAIN LINESTRING AS BLOB #CREATE DOMAIN POLYGON AS BLOB diff --git a/core/src/main/resources/geodb/geodb_h2.sql b/core/src/main/resources/geodb/geodb_h2.sql index 522fd53..561dcf8 100644 --- a/core/src/main/resources/geodb/geodb_h2.sql +++ b/core/src/main/resources/geodb/geodb_h2.sql @@ -10,6 +10,7 @@ CREATE ALIAS ST_AsEWKB FOR "geodb.GeoDB.ST_AsEWKB"; CREATE ALIAS ST_AsEWKT FOR "geodb.GeoDB.ST_AsEWKT"; CREATE ALIAS ST_AsHexEWKB FOR "geodb.GeoDB.ST_AsHexEWKB"; CREATE ALIAS ST_AsText FOR "geodb.GeoDB.ST_AsText"; +CREATE ALIAS ST_AsBinary FOR "geodb.GeoDB.ST_AsBinary"; CREATE ALIAS ST_BBOX FOR "geodb.GeoDB.ST_BBox"; CREATE ALIAS ST_Boundary FOR "geodb.GeoDB.ST_Boundary"; CREATE ALIAS ST_Buffer FOR "geodb.GeoDB.ST_Buffer"; diff --git a/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java b/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java index 94b918c..6741c94 100644 --- a/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java +++ b/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java @@ -1,9 +1,11 @@ package geodb; import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; import java.io.IOException; import java.io.InputStream; @@ -19,6 +21,7 @@ import com.vividsolutions.jts.io.InputStreamInStream; import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKBReader; +import com.vividsolutions.jts.io.WKTReader; public abstract class GeoDBExtraFunctionsTest extends GeoDBTestSupport { /** @@ -160,6 +163,71 @@ private void insertThreePoints() throws SQLException{ st.close(); } + @Test + public void testEmpty() throws SQLException, IOException, ParseException { + testBooleanPredicate("ST_IsEmpty", + "GEOMETRYCOLLECTION EMPTY", + "POLYGON((1 2, 3 4, 5 6, 1 2))"); + } + + @Test + public void testSimple() throws SQLException, IOException, ParseException { + testBooleanPredicate("ST_IsSimple", + "POLYGON((1 2, 3 4, 5 6, 1 2))", + "LINESTRING(1 1,2 2,2 3.5,1 3,1 2,2 1)"); + } + + @Test + public void testValid() throws SQLException, IOException, ParseException { + testBooleanPredicate("ST_IsValid", + "LINESTRING(0 0, 1 1)", + "POLYGON((0 0, 1 1, 1 2, 1 1, 0 0))"); + } + + /** + * Tests a predicate that takes one geometry as an argument and returns a + * boolean value. + * + * @param predicate + * the predicate to test. + * @param wktPass + * the WKT that should pass. + * @param wktFail + * the WKT that should fail. + * @throws SQLException + * if unable to run the test in the database. + */ + private void testBooleanPredicate(final String predicate, + final String wktPass, final String wktFail) throws SQLException { + Connection cx = getConnection(); + Statement st = cx.createStatement(); + + // Test the passing condition. + ResultSet rs = st.executeQuery("VALUES " + predicate + "(" + + "ST_GeomFromText('" + wktPass + "', 4326))"); + rs.next(); + boolean result = rs.getBoolean(1); + rs.close(); + assertTrue(result); + + // Test the failing condition. + rs = st.executeQuery("VALUES " + predicate + "(" + "ST_GeomFromText('" + + wktFail + "', 4326))"); + rs.next(); + result = rs.getBoolean(1); + rs.close(); + assertFalse(result); + + // Test the null argument. + rs = st.executeQuery("VALUES " + predicate + "(null)"); + rs.next(); + result = rs.getBoolean(1); + rs.close(); + assertFalse(result); + + st.close(); + } + @Test public void testContains() throws SQLException, IOException, ParseException { testBooleanPredicate("ST_Contains", @@ -264,8 +332,8 @@ private void testBooleanPredicate(final String predicate, assertFalse(result); // Test the first null. - rs = st.executeQuery("VALUES " + predicate + "(null," + "ST_GeomFromText('" + wktBFail - + "', 4326))"); + rs = st.executeQuery("VALUES " + predicate + "(null," + + "ST_GeomFromText('" + wktBPass + "', 4326))"); rs.next(); result = rs.getBoolean(1); rs.close(); @@ -281,4 +349,213 @@ private void testBooleanPredicate(final String predicate, st.close(); } + + @Test + public void testDWithin() throws SQLException, IOException, ParseException { + final String predicate = "ST_DWithin"; + final String wktA = "POINT(0 0)"; + final String wktBPass = "POINT(7 7)"; + final String wktBFail = "POINT(8 8)"; + + Connection cx = getConnection(); + Statement st = cx.createStatement(); + + // Test the passing condition. + ResultSet rs = st.executeQuery("VALUES " + predicate + "(" + + "ST_GeomFromText('" + wktA + "', 4326)," + + "ST_GeomFromText('" + wktBPass + "', 4326), 10)"); + rs.next(); + boolean result = rs.getBoolean(1); + rs.close(); + assertTrue(result); + + // Test the failing condition. + rs = st.executeQuery("VALUES " + predicate + "(" + "ST_GeomFromText('" + + wktA + "', 4326)," + "ST_GeomFromText('" + wktBFail + + "', 4326), 10)"); + rs.next(); + result = rs.getBoolean(1); + rs.close(); + assertFalse(result); + + // Test the first null. + rs = st.executeQuery("VALUES " + predicate + "(null," + + "ST_GeomFromText('" + wktBPass + "', 4326), 10)"); + rs.next(); + result = rs.getBoolean(1); + rs.close(); + assertFalse(result); + + // Test the second null. + rs = st.executeQuery("VALUES " + predicate + "(" + "ST_GeomFromText('" + + wktA + "', 4326), null, 10)"); + rs.next(); + result = rs.getBoolean(1); + rs.close(); + assertFalse(result); + + st.close(); + } + + @Test + public void testWKB() throws SQLException, IOException, ParseException { + String wkt = "POLYGON((743238 2967416,743238 2967450, 743265 2967450,743265.625 2967416,743238 2967416))"; + int srid = 2249; + Geometry original = new WKTReader().read(wkt); + original.setSRID(srid); + Connection cx = getConnection(); + Statement st = cx.createStatement(); + + ResultSet rs = st + .executeQuery("VALUES ST_GeomFromWKB(ST_AsBinary(ST_GeomFromText('" + + wkt + "', " + srid + ")), " + srid + ")"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream( + binaryStream)); + binaryStream.close(); + rs.close(); + assertEquals(original, geometry); + assertEquals(original.getSRID(), geometry.getSRID()); + + rs = st.executeQuery("VALUES ST_AsBinary(null)"); + rs.next(); + binaryStream = rs.getBinaryStream(1); + rs.close(); + assertNull(binaryStream); + + rs = st.executeQuery("VALUES ST_GeomFromWKB(null, " + srid + ")"); + rs.next(); + binaryStream = rs.getBinaryStream(1); + rs.close(); + assertNull(binaryStream); + + st.close(); + } + + @Test + public void testEWKB() throws SQLException, IOException, ParseException { + String wkt = "POLYGON((743238 2967416,743238 2967450, 743265 2967450,743265.625 2967416,743238 2967416))"; + int srid = 2249; + Geometry original = new WKTReader().read(wkt); + original.setSRID(srid); + Connection cx = getConnection(); + Statement st = cx.createStatement(); + + ResultSet rs = st + .executeQuery("VALUES ST_GeomFromEWKB(ST_AsEWKB(ST_GeomFromText('" + + wkt + "', " + srid + ")))"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream( + binaryStream)); + binaryStream.close(); + rs.close(); + assertEquals(original, geometry); + assertEquals(original.getSRID(), geometry.getSRID()); + + rs = st.executeQuery("VALUES ST_AsEWKB(null)"); + rs.next(); + binaryStream = rs.getBinaryStream(1); + rs.close(); + assertNull(binaryStream); + + rs = st.executeQuery("VALUES ST_GeomFromEWKB(null)"); + rs.next(); + binaryStream = rs.getBinaryStream(1); + rs.close(); + assertNull(binaryStream); + + st.close(); + } + + @Test + public void testWKT() throws SQLException, IOException, ParseException { + String wkt = "POLYGON((743238 2967416,743238 2967450, 743265 2967450,743265.625 2967416,743238 2967416))"; + int srid = 2249; + Geometry original = new WKTReader().read(wkt); + original.setSRID(srid); + Connection cx = getConnection(); + Statement st = cx.createStatement(); + + // Ensure that the EWKT matches the expected pattern. + ResultSet rs = st.executeQuery("VALUES ST_AsText(ST_GeomFromText('" + + wkt + "', " + srid + "))"); + rs.next(); + String ewkt = rs.getString(1); + rs.close(); + String pattern = "^POLYGON[\\s]*[(][(][\\d\\s.,]+[)][)]$"; + assertTrue("'" + ewkt + "' does not match the pattern " + pattern, + ewkt.matches(pattern)); + + rs = st.executeQuery("VALUES ST_GeomFromText(ST_AsText(ST_GeomFromText('" + + wkt + "', " + srid + ")), " + srid + ")"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream( + binaryStream)); + binaryStream.close(); + rs.close(); + assertEquals(original, geometry); + assertEquals(original.getSRID(), geometry.getSRID()); + + rs = st.executeQuery("VALUES ST_AsText(null)"); + rs.next(); + wkt = rs.getString(1); + rs.close(); + assertNull(wkt); + + rs = st.executeQuery("VALUES ST_GeomFromText(null, " + srid + ")"); + rs.next(); + binaryStream = rs.getBinaryStream(1); + rs.close(); + assertNull(binaryStream); + + st.close(); + } + + @Test + public void testEWKT() throws SQLException, IOException, ParseException { + String wkt = "POLYGON((743238 2967416,743238 2967450, 743265 2967450,743265.625 2967416,743238 2967416))"; + int srid = 2249; + Geometry original = new WKTReader().read(wkt); + original.setSRID(srid); + Connection cx = getConnection(); + Statement st = cx.createStatement(); + + // Ensure that the EWKT matches the expected pattern. + ResultSet rs = st.executeQuery("VALUES ST_AsEWKT(ST_GeomFromText('" + + wkt + "', " + srid + "))"); + rs.next(); + String ewkt = rs.getString(1); + rs.close(); + String pattern = "^SRID=" + srid + + ";POLYGON[\\s]*[(][(][\\d\\s.,]+[)][)]$"; + assertTrue("'" + ewkt + "' does not match the pattern " + pattern, + ewkt.matches(pattern)); + + rs = st.executeQuery("VALUES ST_GeomFromEWKT(ST_AsEWKT(ST_GeomFromText('" + + wkt + "', " + srid + ")))"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream( + binaryStream)); + rs.close(); + assertEquals(original, geometry); + assertEquals(original.getSRID(), geometry.getSRID()); + + rs = st.executeQuery("VALUES ST_AsEWKT(null)"); + rs.next(); + ewkt = rs.getString(1); + rs.close(); + assertNull(ewkt); + + rs = st.executeQuery("VALUES ST_GeomFromEWKT(null)"); + rs.next(); + binaryStream = rs.getBinaryStream(1); + rs.close(); + assertNull(binaryStream); + + st.close(); + } } From 148a91fd3a36cf092850ca08333abc49ed13d63a Mon Sep 17 00:00:00 2001 From: Lonny Date: Fri, 7 Mar 2014 22:07:56 -0700 Subject: [PATCH 5/6] Added DETERMINISTIC and RETURNS NULL ON NULL INPUT to most functions. Fixed a couple data types. --- core/src/main/resources/geodb/geodb_derby.sql | 124 +++++++++++++----- 1 file changed, 90 insertions(+), 34 deletions(-) diff --git a/core/src/main/resources/geodb/geodb_derby.sql b/core/src/main/resources/geodb/geodb_derby.sql index b33556f..0a6a48e 100644 --- a/core/src/main/resources/geodb/geodb_derby.sql +++ b/core/src/main/resources/geodb/geodb_derby.sql @@ -69,7 +69,9 @@ CREATE FUNCTION ST_Area ( ) RETURNS DOUBLE PRECISION language java external name 'geodb.GeoDB.ST_Area' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_AsEWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA @@ -97,14 +99,18 @@ CREATE FUNCTION ST_AsText ( ) RETURNS VARCHAR(32672) language java external name 'geodb.GeoDB.ST_AsText' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_AsBinary ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_AsBinary' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_BBox ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -119,7 +125,9 @@ CREATE FUNCTION ST_Boundary ( ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_Boundary' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Buffer ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, @@ -127,14 +135,18 @@ CREATE FUNCTION ST_Buffer ( ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_Buffer' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Centroid ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_Centroid' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Crosses ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -142,7 +154,9 @@ CREATE FUNCTION ST_Crosses ( ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_Crosses' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Contains ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -150,14 +164,18 @@ CREATE FUNCTION ST_Contains ( ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_Contains' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_ConvexHull ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_ConvexHull' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_DWithin ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -174,7 +192,9 @@ CREATE FUNCTION ST_Disjoint ( ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_Disjoint' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Distance ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -182,7 +202,9 @@ CREATE FUNCTION ST_Distance ( ) RETURNS DOUBLE PRECISION language java external name 'geodb.GeoDB.ST_Distance' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Difference ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -190,14 +212,18 @@ CREATE FUNCTION ST_Difference ( ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_Difference' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Dimension ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA -) RETURNS INT +) RETURNS SMALLINT language java external name 'geodb.GeoDB.ST_Dimension' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; # TODO: Is this the correct return type? CREATE FUNCTION ST_Envelope ( @@ -205,7 +231,9 @@ CREATE FUNCTION ST_Envelope ( ) RETURNS VARCHAR(32672) language java external name 'geodb.GeoDB.ST_Envelope' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Equals ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -213,7 +241,9 @@ CREATE FUNCTION ST_Equals ( ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_Equals' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_GeoHash ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA @@ -258,9 +288,9 @@ CREATE FUNCTION ST_Intersection ( ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_Intersection' - parameter style java; - -#CREATE ALIAS ST_Intersection FOR "geodb.GeoDB.ST_Intersection" + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Intersects ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -268,21 +298,27 @@ CREATE FUNCTION ST_Intersects ( ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_Intersects' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_IsEmpty ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_IsEmpty' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_IsSimple ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_IsSimple' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_IsValid ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA @@ -323,7 +359,9 @@ CREATE FUNCTION ST_Overlaps ( ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_Overlaps' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; # Derby doesn't support function overloading. #CREATE FUNCTION ST_Relate ( @@ -333,7 +371,9 @@ CREATE FUNCTION ST_Overlaps ( #) RETURNS BOOLEAN # language java # external name 'geodb.GeoDB.ST_Relate' -# parameter style java; +# parameter style java +# DETERMINISTIC +# RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Relate ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -341,28 +381,36 @@ CREATE FUNCTION ST_Relate ( ) RETURNS VARCHAR(32672) language java external name 'geodb.GeoDB.ST_Relate' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_SRID ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS INT language java external name 'geodb.GeoDB.ST_SRID' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_X ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS DOUBLE PRECISION language java external name 'geodb.GeoDB.ST_X' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Y ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS DOUBLE PRECISION language java external name 'geodb.GeoDB.ST_Y' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_SetSRID ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, @@ -386,7 +434,9 @@ CREATE FUNCTION ST_SymDifference ( ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_SymDifference' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Touches ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -394,7 +444,9 @@ CREATE FUNCTION ST_Touches ( ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_Touches' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Union ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -402,7 +454,9 @@ CREATE FUNCTION ST_Union ( ) RETURNS LONG VARCHAR FOR BIT DATA language java external name 'geodb.GeoDB.ST_Union' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Within ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, @@ -410,7 +464,9 @@ CREATE FUNCTION ST_Within ( ) RETURNS BOOLEAN language java external name 'geodb.GeoDB.ST_Within' - parameter style java; + parameter style java + DETERMINISTIC + RETURNS NULL ON NULL INPUT; CREATE FUNCTION Version () RETURNS VARCHAR(16) language java @@ -428,11 +484,11 @@ CREATE FUNCTION Version () RETURNS VARCHAR(16) #CREATE DOMAIN GEOMETRY AS BLOB CREATE DERBY AGGREGATE ST_Extent - FOR VARCHAR(32672) FOR BIT DATA + FOR LONG VARCHAR FOR BIT DATA RETURNS LONG VARCHAR FOR BIT DATA EXTERNAL NAME 'geodb.aggregate.Extent'; CREATE DERBY AGGREGATE ST_Union_Aggregate - FOR VARCHAR(32672) FOR BIT DATA + FOR LONG VARCHAR FOR BIT DATA RETURNS LONG VARCHAR FOR BIT DATA EXTERNAL NAME 'geodb.aggregate.Union'; From 918e537c74f56ce9451767c555499169225cb190 Mon Sep 17 00:00:00 2001 From: Lonny Date: Sun, 9 Mar 2014 07:07:26 -0600 Subject: [PATCH 6/6] Added remaining, desired unit tests. Performed final clean-up. --- core/pom.xml | 24 -- core/src/main/java/geodb/GeoDB.java | 61 +-- .../geodb/aggregate/GeoAggregateFunction.java | 10 +- core/src/main/resources/geodb/geodb_derby.sql | 369 +++++++++--------- .../java/geodb/GeoDBExtraFunctionsTest.java | 134 ++++++- 5 files changed, 353 insertions(+), 245 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index b0bceb4..bf449cb 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -57,30 +57,6 @@ 1.5 - - maven-surefire-plugin - - - org.h2.Driver - jdbc:h2:target/geodb - - - - - Test Derby - test - - test - - - - org.apache.derby.jdbc.EmbeddedDriver - jdbc:derby:directory:target/geodb;create=true - - - - - maven-source-plugin diff --git a/core/src/main/java/geodb/GeoDB.java b/core/src/main/java/geodb/GeoDB.java index f2d6275..eb8409a 100644 --- a/core/src/main/java/geodb/GeoDB.java +++ b/core/src/main/java/geodb/GeoDB.java @@ -176,17 +176,17 @@ public static void InitGeoDB(Connection cx) throws SQLException { } //create the GeoDB metadata table - if (tableExists(cx, null, geoDbTableName, "TABLE")) { - st.execute("DROP TABLE " + geoDbTableName); + if (!tableExists(cx, null, geoDbTableName, "TABLE")) { + st.execute("CREATE TABLE " + geoDbTableName + " (checksum VARCHAR(4))"); } - st.execute("CREATE TABLE " + geoDbTableName + " (checksum VARCHAR(4))"); + st.execute("DELETE FROM " + geoDbTableName); st.execute("INSERT INTO " + geoDbTableName + " VALUES ('" + Version() + "')" ); //create the geometry columns table if (!tableExists(cx, null, "geometry_columns", "TABLE")) { st.execute("CREATE TABLE geometry_columns (f_table_schema VARCHAR(128), " + - "f_table_name VARCHAR(128), f_geometry_column VARCHAR(128), coord_dimension INTEGER, " + - "srid INTEGER, type VARCHAR(30))"); + "f_table_name VARCHAR(128), f_geometry_column VARCHAR(128), coord_dimension INT, " + + "srid INT, type VARCHAR(30))"); } } finally { @@ -261,9 +261,9 @@ public static void AddGeometryColumn(Connection cx, String schema, String table, StringBuilder sql = new StringBuilder(); sql.append("ALTER TABLE ").append(tbl(schema, table)); sql.append(" ADD COLUMN ").append(esc(column)).append(' ') - .append(getType(cx, type)); + .append(getGeometryColumnType(cx, type)); if (isH2(cx)) { - sql.append(" COMMENT '").append(getType(cx, type)).append("'"); + sql.append(" COMMENT '").append(getGeometryColumnType(cx, type)).append("'"); } st.execute(sql.toString()); } @@ -271,21 +271,20 @@ public static void AddGeometryColumn(Connection cx, String schema, String table, finally { rs.close(); } - - if (schema == null) { - schema = getDefaultSchema(cx); - } + + schema = schema != null ? schema : getDefaultSchema(cx); if (!"GEOMETRY".equals(type) && !"GEOMETRYCOLLECTION".equals(type)) { String sql = "ALTER TABLE " + tbl(schema, table) + " ADD CONSTRAINT " + esc(geotypeConstraint(schema, table, column)) + " CHECK "; - if (isH2(cx)) { + if (!isH2(cx)) { + sql += '('; + } sql += esc(column) + " IS NULL OR " - + "GeometryType(" + esc(column) + ") = '" + type + "'";} - else { - sql += "(" + esc(column) + " IS NULL OR " - + "GeometryType(" + esc(column) + ") = '" + type + "')"; + + "GeometryType(" + esc(column) + ") = '" + type + "'"; + if (!isH2(cx)) { + sql += ')'; } st.execute(sql); } @@ -298,7 +297,19 @@ public static void AddGeometryColumn(Connection cx, String schema, String table, } } - private static Object getType(Connection cx, String type) + /** + * Returns the geometry column type that is appropriate for the current + * database. + * + * @param cx + * the database connection. + * @param type + * the default type. + * @return the database-specific type. + * @throws SQLException + * if unable to determine the current database. + */ + private static Object getGeometryColumnType(Connection cx, String type) throws SQLException { if (isH2(cx)) { return type; @@ -335,9 +346,7 @@ public static void DropGeometryColumn(Connection cx, String schema, String table //check the case of a view boolean isView = tableExists(cx, schema, table, "VIEW"); - if (schema == null) { - schema = getDefaultSchema(cx); - } + schema = schema != null ? schema : getDefaultSchema(cx); final String constraintName = geotypeConstraint(schema,table,column); boolean constraintExists = true; String ifExistsClause = ""; @@ -399,9 +408,7 @@ public static void DropGeometryColumnsProc(String schema, String table) throws S public static void DropGeometryColumns(Connection cx, String schema, String table) throws SQLException { Statement st = cx.createStatement(); try { - if (schema == null) { - schema = getDefaultSchema(cx); - } + schema = schema != null ? schema : getDefaultSchema(cx); //look up the geometry column entries StringBuffer sql = new StringBuffer(); @@ -419,7 +426,7 @@ public static void DropGeometryColumns(Connection cx, String schema, String tabl st.close(); } } - + // // Geometry Outputs // @@ -436,7 +443,7 @@ public static String ST_AsText( byte[] wkb ) { } /** - * Return the Well-Known Text (WKT) representation of the geometry with SRID meta data. + * Return the Extended Well-Known Text (EWKT) representation of the geometry with SRID meta data. */ public static String ST_AsEWKT( byte[] wkb ) { if ( wkb == null ) { @@ -459,7 +466,7 @@ public static byte[] ST_AsBinary( byte[] wkb ) { } /** - * Return the Extended Well-Known Binary (WKB) representation of the geometry with SRID meta data. + * Return the Extended Well-Known Binary (EWKB) representation of the geometry with SRID meta data. */ public static byte[] ST_AsEWKB( byte[] wkb ) { return wkb; @@ -516,7 +523,7 @@ public static byte[] ST_GeomFromEWKT (String wkt) { return gToWKB(gFromEWKT(wkt)); } - + /** * Return a specified ST_Geometry value from Well-Known Text representation (WKT). */ diff --git a/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java b/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java index 243d862..2489952 100644 --- a/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java +++ b/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java @@ -19,7 +19,7 @@ public abstract class GeoAggregateFunction implements AggregateFunction, Aggregator { - private Geometry createGeometry(InputStream stream) { + private Geometry createGeometry(ByteArrayInputStream stream) { InputStreamInStream inputStreamInStream = new InputStreamInStream(stream); Geometry geometry = null; try { @@ -46,7 +46,7 @@ public final void add(Object arg0) throws SQLException { } } - public final Object getResult() { + public final Object getResult() throws SQLException { Geometry geometryResult = getGeometryResult(); if (geometryResult != null) { return GeoDB.gToWKB(geometryResult); @@ -92,6 +92,10 @@ public void merge(GeoAggregateFunction function) { * @see org.apache.derby.agg.Aggregator#terminate() */ public byte[] terminate() { - return (byte[])getResult(); + try { + return (byte[])getResult(); + } catch (SQLException e) { + throw new IllegalStateException("Failed to get the function's result", e); + } } } \ No newline at end of file diff --git a/core/src/main/resources/geodb/geodb_derby.sql b/core/src/main/resources/geodb/geodb_derby.sql index 0a6a48e..f5f7cf4 100644 --- a/core/src/main/resources/geodb/geodb_derby.sql +++ b/core/src/main/resources/geodb/geodb_derby.sql @@ -1,4 +1,4 @@ -create procedure AddGeometryColumn ( +CREATE PROCEDURE AddGeometryColumn ( IN SPATIAL_SCHEMA VARCHAR(128), IN SPATIAL_TABLE VARCHAR(128), IN SPATIAL_COLUMN VARCHAR(128), @@ -6,109 +6,108 @@ create procedure AddGeometryColumn ( IN SPATIAL_TYPE VARCHAR(128), IN SPATIAL_DIM INT ) - language java - external name 'geodb.GeoDB.AddGeometryColumnProc' - parameter style java - modifies sql data; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.AddGeometryColumnProc' + PARAMETER STYLE JAVA + MODIFIES SQL DATA; -create procedure CreateSpatialIndex ( +CREATE PROCEDURE CreateSpatialIndex ( IN SPATIAL_SCHEMA VARCHAR(128), IN SPATIAL_TABLE VARCHAR(128), IN SPATIAL_COLUMN VARCHAR(128), IN SPATIAL_SRID VARCHAR(16) ) - language java - external name 'geodb.GeoDB.CreateSpatialIndexProc' - parameter style java - modifies sql data; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.CreateSpatialIndexProc' + PARAMETER STYLE JAVA + MODIFIES SQL DATA; -create procedure DropGeometryColumn ( +CREATE PROCEDURE DropGeometryColumn ( IN SPATIAL_SCHEMA VARCHAR(128), IN SPATIAL_TABLE VARCHAR(128), IN SPATIAL_COLUMN VARCHAR(128) ) - language java - external name 'geodb.GeoDB.DropGeometryColumnProc' - parameter style java - modifies sql data; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.DropGeometryColumnProc' + PARAMETER STYLE JAVA + MODIFIES SQL DATA; -create procedure DropGeometryColumns ( +CREATE PROCEDURE DropGeometryColumns ( IN SPATIAL_SCHEMA VARCHAR(128), IN SPATIAL_TABLE VARCHAR(128) ) - language java - external name 'geodb.GeoDB.DropGeometryColumnsProc' - parameter style java - modifies sql data; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.DropGeometryColumnsProc' + PARAMETER STYLE JAVA + MODIFIES SQL DATA; -create procedure DropSpatialIndex ( +CREATE PROCEDURE DropSpatialIndex ( IN SPATIAL_SCHEMA VARCHAR(128), IN SPATIAL_TABLE VARCHAR(128) ) - language java - external name 'geodb.GeoDB.DropSpatialIndexProc' - parameter style java - modifies sql data; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.DropSpatialIndexProc' + PARAMETER STYLE JAVA + MODIFIES SQL DATA; CREATE FUNCTION EnvelopeAsText ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) - language java - external name 'geodb.GeoDB.EnvelopeAsText' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.EnvelopeAsText' + PARAMETER STYLE JAVA; CREATE FUNCTION GeometryType ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) - language java - external name 'geodb.GeoDB.GeometryType' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.GeometryType' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_Area ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS DOUBLE PRECISION - language java - external name 'geodb.GeoDB.ST_Area' - parameter style java - DETERMINISTIC - RETURNS NULL ON NULL INPUT; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Area' + PARAMETER STYLE JAVA + DETERMINISTIC; CREATE FUNCTION ST_AsEWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_AsEWKB' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_AsEWKB' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_AsEWKT ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) - language java - external name 'geodb.GeoDB.ST_AsEWKT' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_AsEWKT' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_AsHexEWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) - language java - external name 'geodb.GeoDB.ST_AsHexEWKB' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_AsHexEWKB' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_AsText ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) - language java - external name 'geodb.GeoDB.ST_AsText' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_AsText' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_AsBinary ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_AsBinary' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_AsBinary' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -116,16 +115,16 @@ CREATE FUNCTION ST_BBox ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_BBox' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_BBox' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_Boundary ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_Boundary' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Boundary' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -133,18 +132,18 @@ CREATE FUNCTION ST_Buffer ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, SPATIAL_DISTANCE DOUBLE PRECISION ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_Buffer' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Buffer' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Centroid ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_Centroid' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Centroid' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -152,9 +151,9 @@ CREATE FUNCTION ST_Crosses ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_Crosses' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Crosses' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -162,18 +161,18 @@ CREATE FUNCTION ST_Contains ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_Contains' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Contains' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_ConvexHull ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_ConvexHull' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_ConvexHull' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -182,17 +181,17 @@ CREATE FUNCTION ST_DWithin ( SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA, SPATIAL_DISTANCE DOUBLE PRECISION ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_DWithin' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_DWithin' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_Disjoint ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_Disjoint' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Disjoint' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -200,9 +199,9 @@ CREATE FUNCTION ST_Distance ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS DOUBLE PRECISION - language java - external name 'geodb.GeoDB.ST_Distance' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Distance' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -210,28 +209,27 @@ CREATE FUNCTION ST_Difference ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_Difference' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Difference' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Dimension ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS SMALLINT - language java - external name 'geodb.GeoDB.ST_Dimension' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Dimension' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; -# TODO: Is this the correct return type? CREATE FUNCTION ST_Envelope ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) - language java - external name 'geodb.GeoDB.ST_Envelope' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Envelope' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -239,56 +237,56 @@ CREATE FUNCTION ST_Equals ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_Equals' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Equals' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_GeoHash ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS VARCHAR(32672) - language java - external name 'geodb.GeoDB.ST_GeoHash' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_GeoHash' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_GeomFromEWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_GeomFromEWKB' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_GeomFromEWKB' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_GeomFromEWKT ( SPATIAL_WKT VARCHAR(32672) ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_GeomFromEWKT' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_GeomFromEWKT' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_GeomFromText ( SPATIAL_WKT VARCHAR(32672), SPATIAL_SRID INTEGER ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_GeomFromText' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_GeomFromText' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_GeomFromWKB ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, SPATIAL_SRID INTEGER ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_GeomFromWKB' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_GeomFromWKB' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_Intersection ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_Intersection' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Intersection' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -296,70 +294,81 @@ CREATE FUNCTION ST_Intersects ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_Intersects' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Intersects' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_IsEmpty ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_IsEmpty' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_IsEmpty' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_IsSimple ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_IsSimple' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_IsSimple' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_IsValid ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_IsValid' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_IsValid' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_MakePoint ( SPATIAL_X DOUBLE PRECISION, SPATIAL_Y DOUBLE PRECISION ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_MakePoint' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_MakePoint' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_MakeBox2D ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_MakeBox2D' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_MakeBox2D' + PARAMETER STYLE JAVA; -CREATE FUNCTION ST_MakeBox2D ( - SPATIAL_X1 DOUBLE PRECISION, - SPATIAL_Y1 DOUBLE PRECISION, - SPATIAL_X2 DOUBLE PRECISION, - SPATIAL_Y2 DOUBLE PRECISION -) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_MakeBox2D' - parameter style java; +# Derby doesn't support function overloading. +#CREATE FUNCTION ST_MakeBox2D ( +# SPATIAL_X1 DOUBLE PRECISION, +# SPATIAL_Y1 DOUBLE PRECISION, +# SPATIAL_X2 DOUBLE PRECISION, +# SPATIAL_Y2 DOUBLE PRECISION +#) RETURNS LONG VARCHAR FOR BIT DATA +# LANGUAGE JAVA +# EXTERNAL NAME 'geodb.GeoDB.ST_MakeBox2D' +# PARAMETER STYLE JAVA; CREATE FUNCTION ST_Overlaps ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_Overlaps' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Overlaps' + PARAMETER STYLE JAVA + DETERMINISTIC + RETURNS NULL ON NULL INPUT; + +CREATE FUNCTION ST_Relate ( + SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, + SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA +) RETURNS VARCHAR(32672) + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Relate' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -369,46 +378,36 @@ CREATE FUNCTION ST_Overlaps ( # SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA, # SPATIAL_INTERSECTION_PATTERN VARCHAR(32672) #) RETURNS BOOLEAN -# language java -# external name 'geodb.GeoDB.ST_Relate' -# parameter style java +# LANGUAGE JAVA +# EXTERNAL NAME 'geodb.GeoDB.ST_Relate' +# PARAMETER STYLE JAVA # DETERMINISTIC # RETURNS NULL ON NULL INPUT; -CREATE FUNCTION ST_Relate ( - SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, - SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA -) RETURNS VARCHAR(32672) - language java - external name 'geodb.GeoDB.ST_Relate' - parameter style java - DETERMINISTIC - RETURNS NULL ON NULL INPUT; - CREATE FUNCTION ST_SRID ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS INT - language java - external name 'geodb.GeoDB.ST_SRID' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_SRID' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_X ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS DOUBLE PRECISION - language java - external name 'geodb.GeoDB.ST_X' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_X' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; CREATE FUNCTION ST_Y ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA ) RETURNS DOUBLE PRECISION - language java - external name 'geodb.GeoDB.ST_Y' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Y' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -416,25 +415,25 @@ CREATE FUNCTION ST_SetSRID ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, SPATIAL_SRID INT ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_SetSRID' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_SetSRID' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_Simplify ( SPATIAL_WKB LONG VARCHAR FOR BIT DATA, SPATIAL_DISTANCE DOUBLE PRECISION ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_Simplify' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Simplify' + PARAMETER STYLE JAVA; CREATE FUNCTION ST_SymDifference ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_SymDifference' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_SymDifference' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -442,9 +441,9 @@ CREATE FUNCTION ST_Touches ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_Touches' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Touches' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -452,9 +451,9 @@ CREATE FUNCTION ST_Union ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS LONG VARCHAR FOR BIT DATA - language java - external name 'geodb.GeoDB.ST_Union' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Union' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; @@ -462,16 +461,16 @@ CREATE FUNCTION ST_Within ( SPATIAL_WKB1 LONG VARCHAR FOR BIT DATA, SPATIAL_WKB2 LONG VARCHAR FOR BIT DATA ) RETURNS BOOLEAN - language java - external name 'geodb.GeoDB.ST_Within' - parameter style java + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.ST_Within' + PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT; CREATE FUNCTION Version () RETURNS VARCHAR(16) - language java - external name 'geodb.GeoDB.Version' - parameter style java; + LANGUAGE JAVA + EXTERNAL NAME 'geodb.GeoDB.Version' + PARAMETER STYLE JAVA; # Derby can't alias types. #CREATE DOMAIN POINT AS BLOB diff --git a/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java b/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java index 6741c94..c38ee9c 100644 --- a/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java +++ b/core/src/test/java/geodb/GeoDBExtraFunctionsTest.java @@ -1,11 +1,7 @@ package geodb; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; import java.io.IOException; import java.io.InputStream; @@ -15,9 +11,13 @@ import java.sql.Statement; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; +import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.io.InputStreamInStream; import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKBReader; @@ -163,6 +163,128 @@ private void insertThreePoints() throws SQLException{ st.close(); } + @Test + public void testArea() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); + Geometry original = GeoDB.gFromWKT( + "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", 4326); + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("VALUES ST_Area(ST_GeomFromText('" + + original.toText() + "', 4326))"); + rs.next(); + double area = rs.getDouble(1); + rs.close(); + assertEquals(original.getArea(), area, 0.0001); + + rs = st.executeQuery("VALUES ST_Area(null)"); + rs.next(); + area = rs.getDouble(1); + assertEquals(-1, area, 0.0001); + rs.close(); + + st.close(); + } + + @Test + public void testCentroid() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); + Statement st = cx.createStatement(); + ResultSet rs = st + .executeQuery("VALUES ST_Centroid(" + + "ST_GeomFromText('MULTIPOINT ( -1 0, -1 2, -1 3, -1 4, -1 7, 0 1, 0 3, 1 1, 2 0, 6 0, 7 8, 9 8, 10 6 )', 4326))"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + rs.close(); + assertTrue(geometry instanceof Point); + Point point = (Point)geometry; + assertEquals(2.30769230769231, point.getX(), 0.00000000000001); + assertEquals(3.30769230769231, point.getY(), 0.00000000000001); + + rs = st.executeQuery("VALUES ST_Centroid(null)"); + rs.next(); + binaryStream = rs.getBinaryStream(1); + rs.close(); + assertNull(binaryStream); + + st.close(); + } + + @Test + public void testSimplify() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); + Statement st = cx.createStatement(); + ResultSet rs = st + .executeQuery("VALUES ST_Simplify(" + + "ST_GeomFromText('POLYGON((0 0, 0 1, 1 1, 1 0, 0.9 0, 0 0))', 4326), .1)"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + rs.close(); + assertTrue(geometry instanceof Polygon); + Polygon polygon = (Polygon)geometry; + assertEquals(5, polygon.getExteriorRing().getNumPoints()); + + st.close(); + } + + @Test + public void testMakePoint() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); + Statement st = cx.createStatement(); + ResultSet rs = st + .executeQuery("VALUES ST_MakePoint(1, 2)"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + rs.close(); + assertTrue(geometry instanceof Point); + Point point = (Point)geometry; + assertEquals(1, point.getX(), 0.00000000000001); + assertEquals(2, point.getY(), 0.00000000000001); + assertEquals(0, point.getSRID()); + + st.close(); + } + + // TODO: ST_MakeBox2D does not create a JTS-formatted WKB. + @Ignore + public void testMakeBox2D() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); + Statement st = cx.createStatement(); + ResultSet rs = st + .executeQuery("VALUES ST_MakeBox2D(" + + "ST_GeomFromText('POINT(0 0)', 4326)," + + "ST_GeomFromText('POINT(1 1)', 4326))"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + rs.close(); + Envelope envelope = geometry.getEnvelopeInternal(); + assertEquals(0, envelope.getMinX(), 0.00000000000001); + assertEquals(0, envelope.getMinY(), 0.00000000000001); + assertEquals(1, envelope.getMaxX(), 0.00000000000001); + assertEquals(1, envelope.getMaxY(), 0.00000000000001); + + st.close(); + } + + @Test + public void testSetSRID() throws SQLException, IOException, ParseException { + Connection cx = getConnection(); + Statement st = cx.createStatement(); + ResultSet rs = st + .executeQuery("VALUES ST_SetSRID(" + + "ST_GeomFromText('POINT(-123.365556 48.428611)', 4326), 3785)"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + rs.close(); + assertEquals(3785, geometry.getSRID()); + + st.close(); + } + @Test public void testEmpty() throws SQLException, IOException, ParseException { testBooleanPredicate("ST_IsEmpty",