From c16a3eb1cc8fdb2c76d81ec9c73d4021e4a9e93c Mon Sep 17 00:00:00 2001 From: ebocher Date: Tue, 9 Jun 2020 11:30:18 +0200 Subject: [PATCH 1/2] Fix POSTGIS issues Fix medata with postgis ewkb --- .../functions/io/shp/SHPDriverFunction.java | 298 +++++++++--------- .../spatial/convert/ST_LineFromWKB.java | 33 +- .../spatial/convert/ST_PointFromWKB.java | 55 ++-- .../spatial/convert/ST_PolyFromWKB.java | 20 +- .../spatial/properties/ST_CoordDim.java | 3 +- .../spatial/properties/ST_GeometryType.java | 3 +- .../properties/ST_GeometryTypeCode.java | 3 +- .../functions/spatial/properties/ST_Is3D.java | 3 +- .../functions/spatial/properties/ST_SRID.java | 3 +- .../functions/io/shp/SHPImportExportTest.java | 57 +++- .../metadata/GeometryTableUtilsTest.java | 28 ++ .../processing/ProcessingFunctionTest.java | 5 +- .../org/h2gis/utilities/GeometryMetaData.java | 98 +++++- 13 files changed, 391 insertions(+), 218 deletions(-) diff --git a/h2gis-functions/src/main/java/org/h2gis/functions/io/shp/SHPDriverFunction.java b/h2gis-functions/src/main/java/org/h2gis/functions/io/shp/SHPDriverFunction.java index 0fd3cf4fb5..8758596431 100644 --- a/h2gis-functions/src/main/java/org/h2gis/functions/io/shp/SHPDriverFunction.java +++ b/h2gis-functions/src/main/java/org/h2gis/functions/io/shp/SHPDriverFunction.java @@ -3,21 +3,20 @@ * . H2GIS is developed by CNRS * . * - * This code is part of the H2GIS project. H2GIS is free software; - * you can redistribute it and/or modify it under the terms of the GNU - * Lesser General Public License as published by the Free Software Foundation; - * version 3.0 of the License. + * This code is part of the H2GIS project. H2GIS is free software; you can + * redistribute it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation; version 3.0 of + * the License. * - * H2GIS is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details . + * H2GIS is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details . * * * For more information, please consult: * or contact directly: info_at_h2gis.org */ - package org.h2gis.functions.io.shp; import org.h2.table.Column; @@ -48,16 +47,18 @@ import java.util.regex.Pattern; import org.h2gis.utilities.GeometryTableUtilities; import org.h2gis.utilities.Tuple; +import org.locationtech.jts.geom.Geometry; /** * Read/Write Shape files + * * @author Nicolas Fortin * @author Sylvain PALOMINOS (UBS 2019) */ public class SHPDriverFunction implements DriverFunction { + public static String DESCRIPTION = "ESRI shapefile"; private static final int BATCH_MAX_SIZE = 200; - @Override public void exportTable(Connection connection, String tableReference, File fileName, ProgressVisitor progress) throws SQLException, IOException { @@ -66,66 +67,67 @@ public void exportTable(Connection connection, String tableReference, File fileN @Override public void exportTable(Connection connection, String tableReference, File fileName, boolean deleteFiles, ProgressVisitor progress) throws SQLException, IOException { - exportTable( connection, tableReference, fileName, null, deleteFiles, progress); + exportTable(connection, tableReference, fileName, null, deleteFiles, progress); } @Override - public void exportTable(Connection connection, String tableReference, File fileName, String options, boolean deleteFiles,ProgressVisitor progress) throws SQLException, IOException { + public void exportTable(Connection connection, String tableReference, File fileName, String options, boolean deleteFiles, ProgressVisitor progress) throws SQLException, IOException { if (!FileUtil.isExtensionWellFormated(fileName, "shp")) { throw new SQLException("Only .shp extension is supported"); } - if(deleteFiles){ - //Delete all shapeFile extensions - String path = fileName.getAbsolutePath(); - String nameWithoutExt = path.substring(0, path.lastIndexOf('.')); - Files.deleteIfExists(fileName.toPath()); - Files.deleteIfExists(new File(nameWithoutExt+".dbf").toPath()); - Files.deleteIfExists(new File(nameWithoutExt+".shx").toPath()); - Files.deleteIfExists(new File(nameWithoutExt+".prj").toPath()); - } - final boolean isH2 = JDBCUtilities.isH2DataBase(connection); - String regex = ".*(?i)\\b(select|from)\\b.*"; - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(tableReference); - if (matcher.find()) { - if (tableReference.startsWith("(") && tableReference.endsWith(")")) { - PreparedStatement ps = connection.prepareStatement(tableReference, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - JDBCUtilities.attachCancelResultSet(ps, progress); - ResultSet resultSet = ps.executeQuery(); - int recordCount = 0; - resultSet.last(); - recordCount = resultSet.getRow(); - resultSet.beforeFirst(); - ProgressVisitor copyProgress = progress.subProcess(recordCount); - Tuple spatialFieldNameAndIndex = GeometryTableUtilities.getFirstGeometryColumnNameAndIndex(resultSet); - int srid = doExport(spatialFieldNameAndIndex.second(), resultSet, recordCount, fileName, progress, options); - String path = fileName.getAbsolutePath(); - String nameWithoutExt = path.substring(0, path.lastIndexOf('.')); - PRJUtil.writePRJ(connection, srid, new File(nameWithoutExt + ".prj")); - copyProgress.endOfProgress(); - } else { - throw new SQLException("The select query must be enclosed in parenthesis: '(SELECT * FROM ORDERS)'."); - } - } else { - TableLocation location = TableLocation.parse(tableReference, isH2); - int recordCount = JDBCUtilities.getRowCount(connection, tableReference); + if (deleteFiles) { + //Delete all shapeFile extensions + String path = fileName.getAbsolutePath(); + String nameWithoutExt = path.substring(0, path.lastIndexOf('.')); + Files.deleteIfExists(fileName.toPath()); + Files.deleteIfExists(new File(nameWithoutExt + ".dbf").toPath()); + Files.deleteIfExists(new File(nameWithoutExt + ".shx").toPath()); + Files.deleteIfExists(new File(nameWithoutExt + ".prj").toPath()); + } + final boolean isH2 = JDBCUtilities.isH2DataBase(connection); + String regex = ".*(?i)\\b(select|from)\\b.*"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(tableReference); + if (matcher.find()) { + if (tableReference.startsWith("(") && tableReference.endsWith(")")) { + PreparedStatement ps = connection.prepareStatement(tableReference, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + JDBCUtilities.attachCancelResultSet(ps, progress); + ResultSet resultSet = ps.executeQuery(); + int recordCount = 0; + resultSet.last(); + recordCount = resultSet.getRow(); + resultSet.beforeFirst(); ProgressVisitor copyProgress = progress.subProcess(recordCount); - // Read Geometry Index and type - Tuple spatialFieldNameAndIndex = GeometryTableUtilities.getFirstGeometryColumnNameAndIndex(connection, TableLocation.parse(tableReference, isH2)); - Statement st = connection.createStatement(); - JDBCUtilities.attachCancelResultSet(st, progress); - ResultSet rs = st.executeQuery(String.format("select * from %s", location.toString())); - doExport(spatialFieldNameAndIndex.second(), rs, recordCount, fileName, copyProgress, options); + Tuple spatialFieldNameAndIndex = GeometryTableUtilities.getFirstGeometryColumnNameAndIndex(resultSet); + int srid = doExport(spatialFieldNameAndIndex.second(), resultSet, recordCount, fileName, progress, options); String path = fileName.getAbsolutePath(); String nameWithoutExt = path.substring(0, path.lastIndexOf('.')); - PRJUtil.writePRJ(connection, location, spatialFieldNameAndIndex.first(), new File(nameWithoutExt + ".prj")); + PRJUtil.writePRJ(connection, srid, new File(nameWithoutExt + ".prj")); copyProgress.endOfProgress(); + } else { + throw new SQLException("The select query must be enclosed in parenthesis: '(SELECT * FROM ORDERS)'."); } + } else { + TableLocation location = TableLocation.parse(tableReference, isH2); + int recordCount = JDBCUtilities.getRowCount(connection, tableReference); + ProgressVisitor copyProgress = progress.subProcess(recordCount); + // Read Geometry Index and type + Tuple spatialFieldNameAndIndex = GeometryTableUtilities.getFirstGeometryColumnNameAndIndex(connection, TableLocation.parse(tableReference, isH2)); + Statement st = connection.createStatement(); + JDBCUtilities.attachCancelResultSet(st, progress); + ResultSet rs = st.executeQuery(String.format("select * from %s", location.toString())); + doExport(spatialFieldNameAndIndex.second(), rs, recordCount, fileName, copyProgress, options); + String path = fileName.getAbsolutePath(); + String nameWithoutExt = path.substring(0, path.lastIndexOf('.')); + PRJUtil.writePRJ(connection, location, spatialFieldNameAndIndex.first(), new File(nameWithoutExt + ".prj")); + copyProgress.endOfProgress(); + } } /** * Save a table or a query to a shpfile + * * @param connection Active connection, do not close this connection. * @param tableReference [[catalog.]schema.]table reference * @param fileName File path to write, if exists it may be replaced @@ -135,19 +137,20 @@ public void exportTable(Connection connection, String tableReference, File fileN * @throws IOException */ @Override - public void exportTable(Connection connection, String tableReference, File fileName, String encoding,ProgressVisitor progress) throws SQLException, IOException { - exportTable( connection, tableReference, fileName, encoding, false, progress); + public void exportTable(Connection connection, String tableReference, File fileName, String encoding, ProgressVisitor progress) throws SQLException, IOException { + exportTable(connection, tableReference, fileName, encoding, false, progress); } - /** + /** * Method to export a resulset into a shapefile + * * @param fileName File path to write, if exists it may be replaced * @param progress to display the IO progress * @param encoding File encoding, null will use default encoding - * @throws java.sql.SQLException + * @throws java.sql.SQLException */ private int doExport(Integer spatialFieldIndex, ResultSet rs, int recordCount, File fileName, ProgressVisitor progress, String encoding) throws SQLException, IOException { - int srid =0; + int srid = 0; ShapeType shapeType = null; try { ResultSetMetaData resultSetMetaData = rs.getMetaData(); @@ -167,13 +170,13 @@ private int doExport(Integer spatialFieldIndex, ResultSet rs, int recordCount, F } if (shpDriver == null) { // If there is not shape type constraint read the first geometry and use the same type - byte[] wkb = rs.getBytes(spatialFieldIndex); + Geometry wkb = (Geometry) rs.getObject(spatialFieldIndex); if (wkb != null) { - GeometryMetaData gm = GeometryMetaData.getMetaData(wkb); + GeometryMetaData gm = GeometryMetaData.getMetaData(wkb); if (srid == 0) { srid = gm.SRID; } - shapeType = getShapeTypeFromGeometryMetaData(gm); + shapeType = getShapeTypeFromGeometryMetaData(gm); } if (shapeType != null) { shpDriver = new SHPDriver(); @@ -197,10 +200,9 @@ private int doExport(Integer spatialFieldIndex, ResultSet rs, int recordCount, F return srid; } - @Override public String getFormatDescription(String format) { - if(format.equalsIgnoreCase("shp")) { + if (format.equalsIgnoreCase("shp")) { return DESCRIPTION; } else { return ""; @@ -214,12 +216,12 @@ public IMPORT_DRIVER_TYPE getImportDriverType() { @Override public String[] getImportFormats() { - return new String[] {"shp"}; + return new String[]{"shp"}; } @Override public String[] getExportFormats() { - return new String[] {"shp"}; + return new String[]{"shp"}; } @Override @@ -229,7 +231,7 @@ public boolean isSpatialFormat(String extension) { @Override public void importFile(Connection connection, String tableReference, File fileName, ProgressVisitor progress) throws SQLException, IOException { - importFile(connection, tableReference, fileName, null, progress); + importFile(connection, tableReference, fileName, null, progress); } /** @@ -237,7 +239,8 @@ public void importFile(Connection connection, String tableReference, File fileNa * @param connection Active connection, do not close this connection. * @param tableReference [[catalog.]schema.]table reference * @param fileName File path to read - * @param forceEncoding If defined use this encoding instead of the one defined in dbf header. + * @param forceEncoding If defined use this encoding instead of the one + * defined in dbf header. * @param progress * @throws SQLException Table write error * @throws IOException File read error @@ -248,103 +251,106 @@ public void importFile(Connection connection, String tableReference, File fileNa } @Override - public void importFile(Connection connection, String tableReference, File fileName, boolean deleteTables,ProgressVisitor progress - ) throws SQLException, IOException { + public void importFile(Connection connection, String tableReference, File fileName, boolean deleteTables, ProgressVisitor progress + ) throws SQLException, IOException { importFile(connection, tableReference, fileName, null, deleteTables, progress); } @Override - public void importFile(Connection connection, String tableReference, File fileName, String options, boolean deleteTables,ProgressVisitor progress) throws SQLException, IOException { + public void importFile(Connection connection, String tableReference, File fileName, String options, boolean deleteTables, ProgressVisitor progress) throws SQLException, IOException { final boolean isH2 = JDBCUtilities.isH2DataBase(connection); if (FileUtil.isFileImportable(fileName, "shp")) { - if(deleteTables) { - TableLocation requestedTable = TableLocation.parse(tableReference, isH2); - String table = requestedTable.getTable(); - Statement stmt = connection.createStatement(); - stmt.execute("DROP TABLE IF EXISTS " + table); - stmt.close(); - } - SHPDriver shpDriver = new SHPDriver(); - shpDriver.initDriverFromFile(fileName, options); - ProgressVisitor copyProgress = progress.subProcess((int)(shpDriver.getRowCount() / BATCH_MAX_SIZE)); - // PostGIS does not show sql - String lastSql = ""; - try { - DbaseFileHeader dbfHeader = shpDriver.getDbaseFileHeader(); - ShapefileHeader shpHeader = shpDriver.getShapeFileHeader(); - final TableLocation parse; - int srid; - try ( - // Build CREATE TABLE sql request - Statement st = connection.createStatement()) { - String types = DBFDriverFunction.getSQLColumnTypes(dbfHeader, isH2); - if(!types.isEmpty()) { - types = ", " + types; - } parse = TableLocation.parse(tableReference, isH2); - List otherCols = new ArrayList(dbfHeader.getNumFields() + 1); - otherCols.add(new Column("THE_GEOM", 0)); - for(int idColumn = 0; idColumn < dbfHeader.getNumFields(); idColumn++) { - otherCols.add(new Column(dbfHeader.getFieldName(idColumn), 0)); - } String pkColName = FileEngine.getUniqueColumnName(H2TableIndex.PK_COLUMN_NAME, otherCols); - srid = PRJUtil.getSRID(shpDriver.prjFile); - shpDriver.setSRID(srid); - if(isH2) { - //H2 Syntax - st.execute(String.format("CREATE TABLE %s ("+ pkColName + " SERIAL , the_geom GEOMETRY(%s, %d) %s)", parse, - getSFSGeometryType(shpHeader),srid, types)); - } else { - // PostgreSQL Syntax - lastSql = String.format("CREATE TABLE %s ("+ pkColName + " SERIAL PRIMARY KEY, the_geom GEOMETRY(%s, %d) %s)", parse, - getPostGISSFSGeometryType(shpHeader),srid, types); - st.execute(lastSql); - } + if (deleteTables) { + TableLocation requestedTable = TableLocation.parse(tableReference, isH2); + String table = requestedTable.getTable(); + Statement stmt = connection.createStatement(); + stmt.execute("DROP TABLE IF EXISTS " + table); + stmt.close(); } + SHPDriver shpDriver = new SHPDriver(); + shpDriver.initDriverFromFile(fileName, options); + ProgressVisitor copyProgress = progress.subProcess((int) (shpDriver.getRowCount() / BATCH_MAX_SIZE)); + // PostGIS does not show sql + String lastSql = ""; try { - lastSql = String.format("INSERT INTO %s VALUES (DEFAULT, %s )", parse, - DBFDriverFunction.getQuestionMark(dbfHeader.getNumFields() + 1)); - connection.setAutoCommit(false); - try (PreparedStatement preparedStatement = connection.prepareStatement(lastSql)) { - long batchSize = 0; - for (int rowId = 0; rowId < shpDriver.getRowCount(); rowId++) { - Value[] values = shpDriver.getRow(rowId); - for (int columnId = 0; columnId < values.length; columnId++) { - preparedStatement.setObject(columnId + 1, values[columnId].getObject()); + DbaseFileHeader dbfHeader = shpDriver.getDbaseFileHeader(); + ShapefileHeader shpHeader = shpDriver.getShapeFileHeader(); + final TableLocation parse; + int srid; + try ( + // Build CREATE TABLE sql request + Statement st = connection.createStatement()) { + String types = DBFDriverFunction.getSQLColumnTypes(dbfHeader, isH2); + if (!types.isEmpty()) { + types = ", " + types; + } + parse = TableLocation.parse(tableReference, isH2); + List otherCols = new ArrayList(dbfHeader.getNumFields() + 1); + otherCols.add(new Column("THE_GEOM", 0)); + for (int idColumn = 0; idColumn < dbfHeader.getNumFields(); idColumn++) { + otherCols.add(new Column(dbfHeader.getFieldName(idColumn), 0)); + } + String pkColName = FileEngine.getUniqueColumnName(H2TableIndex.PK_COLUMN_NAME, otherCols); + srid = PRJUtil.getSRID(shpDriver.prjFile); + shpDriver.setSRID(srid); + if (isH2) { + //H2 Syntax + st.execute(String.format("CREATE TABLE %s (" + pkColName + " SERIAL , the_geom GEOMETRY(%s, %d) %s)", parse, + getSFSGeometryType(shpHeader), srid, types)); + } else { + // PostgreSQL Syntax + lastSql = String.format("CREATE TABLE %s (" + pkColName + " SERIAL PRIMARY KEY, the_geom GEOMETRY(%s, %d) %s)", parse, + getPostGISSFSGeometryType(shpHeader), srid, types); + st.execute(lastSql); + } + } + try { + lastSql = String.format("INSERT INTO %s VALUES (DEFAULT, %s )", parse, + DBFDriverFunction.getQuestionMark(dbfHeader.getNumFields() + 1)); + connection.setAutoCommit(false); + try (PreparedStatement preparedStatement = connection.prepareStatement(lastSql)) { + long batchSize = 0; + for (int rowId = 0; rowId < shpDriver.getRowCount(); rowId++) { + Value[] values = shpDriver.getRow(rowId); + for (int columnId = 0; columnId < values.length; columnId++) { + preparedStatement.setObject(columnId + 1, values[columnId].getObject()); + } + preparedStatement.addBatch(); + batchSize++; + if (batchSize >= BATCH_MAX_SIZE) { + preparedStatement.executeBatch(); + connection.commit(); + preparedStatement.clearBatch(); + batchSize = 0; + copyProgress.endStep(); + } } - preparedStatement.addBatch(); - batchSize++; - if (batchSize >= BATCH_MAX_SIZE) { + if (batchSize > 0) { preparedStatement.executeBatch(); connection.commit(); - preparedStatement.clearBatch(); - batchSize = 0; - copyProgress.endStep(); } - } - if(batchSize > 0) { - preparedStatement.executeBatch(); - connection.commit(); - } - connection.setAutoCommit(true); + connection.setAutoCommit(true); + } + } catch (Exception ex) { + connection.createStatement().execute("DROP TABLE IF EXISTS " + tableReference); + throw new SQLException(ex.getLocalizedMessage(), ex); } - } catch (Exception ex) { - connection.createStatement().execute("DROP TABLE IF EXISTS " + tableReference); - throw new SQLException(ex.getLocalizedMessage(), ex); + } catch (SQLException ex) { + throw new SQLException(lastSql + "\n" + ex.getLocalizedMessage(), ex); + } finally { + shpDriver.close(); + copyProgress.endOfProgress(); } - } catch (SQLException ex) { - throw new SQLException(lastSql+"\n"+ex.getLocalizedMessage(), ex); - } finally { - shpDriver.close(); - copyProgress.endOfProgress(); - } } } /** * Return the shape type supported by the shapefile format + * * @param meta * @return - * @throws SQLException + * @throws SQLException */ private static ShapeType getShapeTypeFromGeometryMetaData(GeometryMetaData meta) throws SQLException { ShapeType shapeType; @@ -382,7 +388,7 @@ private static ShapeType getShapeTypeFromGeometryMetaData(GeometryMetaData meta) } private static String getSFSGeometryType(ShapefileHeader header) { - switch(header.getShapeType().id) { + switch (header.getShapeType().id) { case 1: return "POINT"; case 11: @@ -409,7 +415,7 @@ private static String getSFSGeometryType(ShapefileHeader header) { } private static String getPostGISSFSGeometryType(ShapefileHeader header) { - switch(header.getShapeType().id) { + switch (header.getShapeType().id) { case 1: return "POINT"; case 11: @@ -433,5 +439,5 @@ private static String getPostGISSFSGeometryType(ShapefileHeader header) { default: return "GEOMETRY"; } - } + } } diff --git a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_LineFromWKB.java b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_LineFromWKB.java index cefd84f625..14bf3ba91d 100644 --- a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_LineFromWKB.java +++ b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_LineFromWKB.java @@ -2,24 +2,25 @@ * H2GIS is a library that brings spatial support to the H2 Database Engine * . H2GIS is developed by CNRS * . - * - * This code is part of the H2GIS project. H2GIS is free software; + *

+ * This code is part of the H2GIS project. H2GIS is free software; * you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; * version 3.0 of the License. - * + *

* H2GIS is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details . - * - * + *

+ *

* For more information, please consult: * or contact directly: info_at_h2gis.org */ package org.h2gis.functions.spatial.convert; +import org.h2.value.ValueGeometry; import org.h2gis.api.DeterministicScalarFunction; import org.h2gis.utilities.GeometryTypeCodes; import org.h2gis.utilities.GeometryMetaData; @@ -47,7 +48,7 @@ public ST_LineFromWKB() { public String getJavaStaticMethod() { return "toLineString"; } - + /** * Convert WKT into a LinearRing * @param bytes Byte array @@ -58,7 +59,7 @@ public String getJavaStaticMethod() { public static Geometry toLineString(byte[] bytes) throws SQLException, IOException { return toLineString(bytes, 0); } - + /** * Convert WKT into a LinearRing @@ -69,19 +70,15 @@ public static Geometry toLineString(byte[] bytes) throws SQLException, IOExcepti * @throws java.io.IOException */ public static Geometry toLineString(byte[] bytes, int srid) throws SQLException, IOException { - if(bytes==null) { + if (bytes == null) { return null; } - WKBReader wkbReader = new WKBReader(); - try { - if(GeometryMetaData.getMetaData(bytes).geometryTypeCode != GeometryTypeCodes.LINESTRING) { - throw new SQLException("Provided WKB is not a LINESTRING."); - } - Geometry geometry = wkbReader.read(bytes); - geometry.setSRID(srid); - return geometry; - } catch (ParseException ex) { - throw new SQLException("ParseException while evaluating ST_LineFromWKB",ex); + ValueGeometry valueGeometry = ValueGeometry.get(bytes); + if (valueGeometry.getTypeAndDimensionSystem() != GeometryTypeCodes.LINESTRING) { + throw new SQLException("Provided WKB is not a POINT."); } + Geometry geometry = valueGeometry.getGeometry(); + geometry.setSRID(srid); + return geometry; } } diff --git a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_PointFromWKB.java b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_PointFromWKB.java index 3ebcff19a9..a07e695d02 100644 --- a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_PointFromWKB.java +++ b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_PointFromWKB.java @@ -2,24 +2,25 @@ * H2GIS is a library that brings spatial support to the H2 Database Engine * . H2GIS is developed by CNRS * . - * - * This code is part of the H2GIS project. H2GIS is free software; + *

+ * This code is part of the H2GIS project. H2GIS is free software; * you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; * version 3.0 of the License. - * + *

* H2GIS is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details . - * - * + *

+ *

* For more information, please consult: * or contact directly: info_at_h2gis.org */ package org.h2gis.functions.spatial.convert; +import org.h2.value.ValueGeometry; import org.h2gis.api.DeterministicScalarFunction; import org.h2gis.utilities.GeometryTypeCodes; import org.h2gis.utilities.GeometryMetaData; @@ -32,21 +33,19 @@ /** * Convert Well Known Binary into a POINT. + * * @author Erwan Bocher */ -public class ST_PointFromWKB extends DeterministicScalarFunction{ +public class ST_PointFromWKB extends DeterministicScalarFunction { + - - public ST_PointFromWKB(){ + public ST_PointFromWKB() { addProperty(PROP_REMARKS, "Convert Well Known Binary into a POINT.\n If an SRID is not specified, it defaults to 0."); } - @Override - public String getJavaStaticMethod() { - return "toPoint"; - } - - /** + + /** * Convert WKT into a Point + * * @param bytes Byte array * @return Point instance of null if bytes null * @throws SQLException WKB Parse error @@ -57,26 +56,28 @@ public static Geometry toPoint(byte[] bytes) throws SQLException, IOException { /** * Convert WKT into a Point + * * @param bytes Byte array - * @param srid SRID + * @param srid SRID * @return Point instance of null if bytes null * @throws SQLException WKB Parse error */ public static Geometry toPoint(byte[] bytes, int srid) throws SQLException, IOException { - if(bytes==null) { + if (bytes == null) { return null; } - WKBReader wkbReader = new WKBReader(); - try { - if(GeometryMetaData.getMetaData(bytes).geometryTypeCode != GeometryTypeCodes.POINT) { - throw new SQLException("Provided WKB is not a POINT."); - } - Geometry geometry = wkbReader.read(bytes); - geometry.setSRID(srid); - return geometry; - } catch (ParseException ex) { - throw new SQLException("ParseException while evaluating ST_PointFromWKB",ex); + ValueGeometry valueGeometry = ValueGeometry.get(bytes); + if (valueGeometry.getTypeAndDimensionSystem() != GeometryTypeCodes.POINT) { + throw new SQLException("Provided WKB is not a POINT."); } + Geometry geometry = valueGeometry.getGeometry(); + geometry.setSRID(srid); + return geometry; + } + + @Override + public String getJavaStaticMethod() { + return "toPoint"; } - + } diff --git a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_PolyFromWKB.java b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_PolyFromWKB.java index 6cdb25f4d6..09d548af6c 100644 --- a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_PolyFromWKB.java +++ b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/convert/ST_PolyFromWKB.java @@ -20,6 +20,7 @@ package org.h2gis.functions.spatial.convert; +import org.h2.value.ValueGeometry; import org.h2gis.api.DeterministicScalarFunction; import org.h2gis.utilities.GeometryTypeCodes; import org.h2gis.utilities.GeometryMetaData; @@ -68,16 +69,15 @@ public static Geometry toPolygon(byte[] bytes, int srid) throws SQLException, IO if(bytes==null) { return null; } - WKBReader wkbReader = new WKBReader(); - try { - if(GeometryMetaData.getMetaData(bytes).geometryTypeCode != GeometryTypeCodes.POLYGON) { - throw new SQLException("Provided WKB is not a Polygon."); - } - Geometry geometry = wkbReader.read(bytes); - geometry.setSRID(srid); - return geometry; - } catch (ParseException ex) { - throw new SQLException("ParseException while evaluating ST_PolyFromWKB",ex); + if (bytes == null) { + return null; + } + ValueGeometry valueGeometry = ValueGeometry.get(bytes); + if (valueGeometry.getTypeAndDimensionSystem() != GeometryTypeCodes.POLYGON) { + throw new SQLException("Provided WKB is not a POINT."); } + Geometry geometry = valueGeometry.getGeometry(); + geometry.setSRID(srid); + return geometry; } } diff --git a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_CoordDim.java b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_CoordDim.java index 498ea7c74b..29cbc690d0 100644 --- a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_CoordDim.java +++ b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_CoordDim.java @@ -22,6 +22,7 @@ import org.h2gis.api.DeterministicScalarFunction; import org.h2gis.utilities.GeometryMetaData; +import org.locationtech.jts.geom.Geometry; import java.io.IOException; @@ -49,7 +50,7 @@ public String getJavaStaticMethod() { * @return The dimension of the coordinates of the given geometry * @throws IOException */ - public static Integer getCoordinateDimension(byte[] geom) throws IOException { + public static Integer getCoordinateDimension(Geometry geom) throws IOException { if (geom == null) { return null; } diff --git a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_GeometryType.java b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_GeometryType.java index 6f58d1b13d..7a8147e806 100644 --- a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_GeometryType.java +++ b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_GeometryType.java @@ -22,6 +22,7 @@ import org.h2gis.api.DeterministicScalarFunction; import org.h2gis.utilities.GeometryMetaData; +import org.locationtech.jts.geom.Geometry; /** * Return the type of geometry : ST_POINT, ST_LINESTRING, ST_POLYGON... @@ -47,7 +48,7 @@ public String getJavaStaticMethod() { * @param geometry Geometry instance * @return Geometry type for a user-defined type defined in SQL/MM specification. SQL-MM 3: 5.1.4 */ - public static String getGeometryType(byte[] geometry) { + public static String getGeometryType(Geometry geometry) { if(geometry==null) { return null; } diff --git a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_GeometryTypeCode.java b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_GeometryTypeCode.java index 2b27a16122..2e24b93ef5 100644 --- a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_GeometryTypeCode.java +++ b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_GeometryTypeCode.java @@ -22,6 +22,7 @@ import org.h2gis.api.DeterministicScalarFunction; import org.h2gis.utilities.GeometryMetaData; +import org.locationtech.jts.geom.Geometry; import java.io.IOException; @@ -46,7 +47,7 @@ public String getJavaStaticMethod() { * @return Returns the OGC SFS {@link org.h2gis.utilities.GeometryTypeCodes} of a Geometry. This function does not take account of Z nor M. * @throws IOException WKB is not valid. */ - public static Integer getTypeCode(byte[] geometry) throws IOException { + public static Integer getTypeCode(Geometry geometry) throws IOException { if(geometry == null) { return null; } diff --git a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_Is3D.java b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_Is3D.java index 7a9fd2a9d4..7f3c6d9bb3 100644 --- a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_Is3D.java +++ b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_Is3D.java @@ -22,6 +22,7 @@ import org.h2gis.api.DeterministicScalarFunction; import org.h2gis.utilities.GeometryMetaData; +import org.locationtech.jts.geom.Geometry; import java.io.IOException; @@ -50,7 +51,7 @@ public String getJavaStaticMethod() { * @return * @throws IOException */ - public static int is3D(byte[] geom) throws IOException { + public static int is3D(Geometry geom) throws IOException { if (geom == null) { return 0; } diff --git a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_SRID.java b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_SRID.java index 58f52e81cc..7c69d2b21a 100644 --- a/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_SRID.java +++ b/h2gis-functions/src/main/java/org/h2gis/functions/spatial/properties/ST_SRID.java @@ -22,6 +22,7 @@ import org.h2gis.api.DeterministicScalarFunction; import org.h2gis.utilities.GeometryMetaData; +import org.locationtech.jts.geom.Geometry; import java.io.IOException; @@ -48,7 +49,7 @@ public String getJavaStaticMethod() { * @return SRID value or 0 if input geometry does not have one. * @throws IOException */ - public static Integer getSRID(byte[] geometry) throws IOException { + public static Integer getSRID(Geometry geometry) throws IOException { if(geometry==null) { return 0; } diff --git a/h2gis-functions/src/test/java/org/h2gis/functions/io/shp/SHPImportExportTest.java b/h2gis-functions/src/test/java/org/h2gis/functions/io/shp/SHPImportExportTest.java index dcd2337c7e..b98bef8138 100644 --- a/h2gis-functions/src/test/java/org/h2gis/functions/io/shp/SHPImportExportTest.java +++ b/h2gis-functions/src/test/java/org/h2gis/functions/io/shp/SHPImportExportTest.java @@ -42,6 +42,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -773,12 +774,32 @@ public void testSelectWriteRead() throws Exception { stat.execute("CALL SHPRead('target/lines.shp', 'TABLE_LINESTRINGS_READ');"); ResultSet res = stat.executeQuery("SELECT * FROM TABLE_LINESTRINGS_READ;"); res.next(); - GeometryAsserts.assertGeometryEquals("SRID=4326;MULTILINESTRING ((1 10, 20 15))",res.getObject("THE_GEOM")); + Geometry geom = (Geometry) res.getObject("THE_GEOM"); + assertEquals(4326, geom.getSRID()); + GeometryAsserts.assertGeometryEquals("SRID=4326;MULTILINESTRING ((1 10, 20 15))",geom); res.close(); stat.execute("DROP TABLE IF EXISTS TABLE_LINESTRINGS_READ"); } } + @Test + public void testSelectWriteRead2() throws Exception { + try (Statement stat = connection.createStatement()) { + stat.execute(" DROP TABLE IF EXISTS orbisgis;"+ + "CREATE TABLE orbisgis (id int, the_geom geometry(point, 4326));"+ + "INSERT INTO orbisgis VALUES (1, 'SRID=4326;POINT(10 10)'::GEOMETRY), (2, 'SRID=4326;POINT(1 1)'::GEOMETRY); "); + stat.execute("CALL SHPWrite('target/points.shp', '(SELECT st_buffer(the_geom, 10) as the_geom from orbisgis)', true);"); + stat.execute("CALL SHPRead('target/points.shp', 'TABLE_POINTS_READ', true);"); + ResultSet res = stat.executeQuery("SELECT * FROM TABLE_POINTS_READ;"); + res.next(); + Geometry geom = (Geometry) res.getObject("THE_GEOM"); + assertEquals(4326, geom.getSRID()); + GeometryAsserts.assertGeometryEquals("SRID=4326;MULTIPOLYGON (((0 10.000000000000007, 0.19214719596769747 11.950903220161292, 0.7612046748871375 13.826834323650909, 1.6853038769745545 15.555702330196034, 2.928932188134537 17.071067811865486, 4.444297669803992 18.314696123025463, 6.173165676349122 19.238795325112875, 8.04909677983874 19.807852804032308, 10.000000000000025 20, 11.950903220161308 19.8078528040323, 13.826834323650925 19.238795325112857, 15.555702330196048 18.314696123025435, 17.071067811865497 17.07106781186545, 18.31469612302547 15.555702330195993, 19.238795325112882 13.826834323650862, 19.80785280403231 11.950903220161244, 20 10, 19.807852804032304 8.049096779838717, 19.238795325112868 6.173165676349102, 18.314696123025453 4.444297669803978, 17.071067811865476 2.9289321881345254, 15.555702330196024 1.6853038769745474, 13.826834323650898 0.7612046748871322, 11.950903220161283 0.1921471959676957, 10 0, 8.049096779838719 0.1921471959676957, 6.173165676349103 0.7612046748871322, 4.44429766980398 1.6853038769745474, 2.9289321881345254 2.9289321881345245, 1.6853038769745474 4.444297669803978, 0.7612046748871322 6.173165676349106, 0.19214719596769392 8.049096779838722, 0 10.000000000000007)))",geom); + res.close(); + stat.execute("DROP TABLE IF EXISTS TABLE_POINTS_READ"); + } + } + @Disabled @Test public void exportImportPointPostGIS() throws SQLException, IOException { @@ -792,9 +813,10 @@ public void exportImportPointPostGIS() throws SQLException, IOException { Connection con = ds.getConnection(); Statement stat = con.createStatement(); File shpFile = new File("target/punctual_export_postgis.shp"); + Files.deleteIfExists(shpFile.toPath()); stat.execute("DROP TABLE IF EXISTS PUNCTUAL"); - stat.execute("create table punctual(idarea int primary key, the_geom GEOMETRY(POINTZ))"); - stat.execute("insert into punctual values(1, 'POINT(-10 109 5)')"); + stat.execute("create table punctual(idarea int primary key, the_geom GEOMETRY(POINTZ, 4326))"); + stat.execute("insert into punctual values(1, ST_GEOMFROMTEXT('POINT(-10 109 5)',4326))"); // Create a shape file using table area SHPDriverFunction driver = new SHPDriverFunction(); driver.exportTable(con,"punctual", shpFile,new EmptyProgressVisitor()); @@ -805,10 +827,39 @@ public void exportImportPointPostGIS() throws SQLException, IOException { ResultSet res = stat.executeQuery("SELECT THE_GEOM FROM IMPORT_PUNCTUAL;"); res.next(); Geometry geom = (Geometry) res.getObject(1); + assertEquals(4326, geom.getSRID()); Coordinate coord = geom.getCoordinate(); assertEquals(coord.z, 5, 10E-1); stat.execute("DROP TABLE IF EXISTS IMPORT_PUNCTUAL;"); res.close(); } + + @Disabled + @Test + public void testSelectWriteReadPostGIS() throws Exception { + String url = "jdbc:postgresql://149.202.221.161:5432/?"; + Properties props = new Properties(); + props.setProperty("user", "erwan"); + props.setProperty("password", "th@l@ss@56"); + props.setProperty("url", url); + DataSourceFactory dataSourceFactory = new DataSourceFactoryImpl(); + DataSource ds = dataSourceFactory.createDataSource(props); + Connection con = ds.getConnection(); + try (Statement stat = con.createStatement()) { + stat.execute(" DROP TABLE IF EXISTS orbisgis;"+ + "CREATE TABLE orbisgis (id int, the_geom geometry(point, 4326));"+ + "INSERT INTO orbisgis VALUES (1, ST_GEOMFROMTEXT('POINT(10 10)',4326)), (2, ST_GEOMFROMTEXT('POINT(1 1)',4326)); "); + SHPDriverFunction shpDriverFunction = new SHPDriverFunction(); + shpDriverFunction.exportTable(con,"(SELECT st_buffer(the_geom, 10) as the_geom from orbisgis)", new File("target/points.shp"), null, true , new EmptyProgressVisitor()); + shpDriverFunction.importFile(con,"TABLE_POINTS_READ", new File("target/points.shp"), null, true , new EmptyProgressVisitor()); + ResultSet res = stat.executeQuery("SELECT * FROM TABLE_POINTS_READ;"); + res.next(); + Geometry geom = (Geometry) res.getObject("THE_GEOM"); + assertEquals(4326, geom.getSRID()); + GeometryAsserts.assertGeometryEquals("SRID=4326;MULTIPOLYGON (((0 9.999999999999968, 0.1921471959676886 11.950903220161248, 0.761204674887118 13.826834323650864, 1.685303876974526 15.55570233019599, 2.928932188134495 17.071067811865447, 4.444297669803942 18.314696123025428, 6.173165676349064 19.238795325112854, 8.049096779838678 19.807852804032297, 9.999999999999963 20, 11.950903220161248 19.80785280403231, 13.826834323650868 19.238795325112882, 15.555702330195995 18.31469612302547, 17.071067811865454 17.071067811865497, 18.31469612302544 15.555702330196045, 19.23879532511286 13.826834323650921, 19.8078528040323 11.950903220161305, 20 10, 19.807852804032308 8.049096779838719, 19.238795325112868 6.173165676349106, 18.314696123025456 4.444297669803983, 17.071067811865483 2.9289321881345307, 15.55570233019603 1.6853038769745528, 13.826834323650909 0.7612046748871375, 11.950903220161296 0.19214719596769747, 10.000000000000016 0, 8.049096779838735 0.19214719596769214, 6.173165676349122 0.7612046748871251, 4.444297669803995 1.6853038769745368, 2.9289321881345405 2.9289321881345085, 1.6853038769745616 4.444297669803957, 0.7612046748871428 6.173165676349077, 0.19214719596770102 8.049096779838688, 0 9.999999999999968)))",geom); + res.close(); + stat.execute("DROP TABLE IF EXISTS TABLE_POINTS_READ"); + } + } } diff --git a/h2gis-functions/src/test/java/org/h2gis/functions/spatial/metadata/GeometryTableUtilsTest.java b/h2gis-functions/src/test/java/org/h2gis/functions/spatial/metadata/GeometryTableUtilsTest.java index 27d690fdd6..bc651f37aa 100644 --- a/h2gis-functions/src/test/java/org/h2gis/functions/spatial/metadata/GeometryTableUtilsTest.java +++ b/h2gis-functions/src/test/java/org/h2gis/functions/spatial/metadata/GeometryTableUtilsTest.java @@ -722,5 +722,33 @@ public void testEnvelopeSchemaPostGIS() throws SQLException { statement.execute("DROP SCHEMA IF EXISTS MYSCHEMA CASCADE;"); } + @Test + public void testGetMetadataFromGeometry() throws SQLException { + st.execute("DROP TABLE IF EXISTS POINT3D"); + st.execute("CREATE TABLE POINT3D (gid int , the_geom GEOMETRY(POINTZ, 4326))"); + st.execute("insert into POINT3D VALUES(1, 'SRID=4326;POINTZ(0 0 0)')"); + ResultSet resultSet = st.executeQuery("SELECT THE_GEOM FROM POINT3D"); + resultSet.next(); + GeometryMetaData geomMet = GeometryMetaData.getMetaData((Geometry) resultSet.getObject(1)); + assertEquals(4326, geomMet.SRID); + assertEquals(3, geomMet.dimension); + assertFalse(geomMet.hasM); + assertTrue(geomMet.hasZ); + assertEquals("POINTZ", geomMet.geometryType); + assertEquals(GeometryTypeCodes.POINTZ, geomMet.geometryTypeCode); + st.execute("DROP TABLE IF EXISTS POINT3D"); + st.execute("CREATE TABLE POINT3D (gid int , the_geom GEOMETRY)"); + st.execute("insert into POINT3D VALUES(1, 'SRID=4326;POINTM(0 0 0)')"); + resultSet = st.executeQuery("SELECT THE_GEOM FROM POINT3D"); + resultSet.next(); + geomMet = GeometryMetaData.getMetaData((Geometry) resultSet.getObject(1)); + assertEquals(4326, geomMet.SRID); + assertEquals(3, geomMet.dimension); + assertTrue(geomMet.hasM); + assertFalse(geomMet.hasZ); + assertEquals("POINTM", geomMet.geometryType); + assertEquals(GeometryTypeCodes.POINTM, geomMet.geometryTypeCode); + } + } diff --git a/h2gis-functions/src/test/java/org/h2gis/functions/spatial/processing/ProcessingFunctionTest.java b/h2gis-functions/src/test/java/org/h2gis/functions/spatial/processing/ProcessingFunctionTest.java index 2209d1c646..330d3910ff 100644 --- a/h2gis-functions/src/test/java/org/h2gis/functions/spatial/processing/ProcessingFunctionTest.java +++ b/h2gis-functions/src/test/java/org/h2gis/functions/spatial/processing/ProcessingFunctionTest.java @@ -626,7 +626,7 @@ public void test_ST_Split8() throws Exception { Geometry pols = (Geometry) rs.getObject(1); for (int i = 0; i < pols.getNumGeometries(); i++) { Geometry pol = pols.getGeometryN(i); - assertTrue(ST_CoordDim.getCoordinateDimension(ValueGeometry.getFromGeometry(pol).getBytesNoCopy()) == 2); + assertTrue(ST_CoordDim.getCoordinateDimension(pol) == 2); } rs.close(); } @@ -638,8 +638,7 @@ public void test_ST_Split9() throws Exception { Geometry pols = (Geometry) rs.getObject(1); for (int i = 0; i < pols.getNumGeometries(); i++) { Geometry pol = pols.getGeometryN(i); - assertTrue(ST_CoordDim.getCoordinateDimension( - ValueGeometry.getFromGeometry(pol).getBytesNoCopy()) == 2); + assertTrue(ST_CoordDim.getCoordinateDimension(pol) == 2); } rs.close(); } diff --git a/h2gis-utilities/src/main/java/org/h2gis/utilities/GeometryMetaData.java b/h2gis-utilities/src/main/java/org/h2gis/utilities/GeometryMetaData.java index 5c3a9d23de..ca3dd9d684 100644 --- a/h2gis-utilities/src/main/java/org/h2gis/utilities/GeometryMetaData.java +++ b/h2gis-utilities/src/main/java/org/h2gis/utilities/GeometryMetaData.java @@ -19,10 +19,15 @@ */ package org.h2gis.utilities; +import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.h2.value.ValueGeometry; import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.io.ByteArrayInStream; +import org.locationtech.jts.io.ByteOrderDataInStream; +import org.locationtech.jts.io.ByteOrderValues; +import org.locationtech.jts.io.WKBConstants; /** * Extract Geometry MetaData from various geometry signatures @@ -63,6 +68,21 @@ public class GeometryMetaData { */ public int SRID = 0; + /** + * Geometry type mask that indicates presence of dimension Z. + */ + public static final int EWKB_Z = 0x8000_0000; + + /** + * Geometry type mask that indicates presence of dimension M. + */ + public static final int EWKB_M = 0x4000_0000; + + /** + * Geometry type mask that indicates presence of SRID. + */ + public static final int EWKB_SRID = 0x2000_0000; + /** * 0-based type names of geometries, subtract 1 from type code to get index * in this array. @@ -144,10 +164,13 @@ public void initGeometryType() { sfs_geometryType = geometryType; if (hasM && hasZ) { geometryType += "ZM"; + dimension = 4; } else if (hasZ) { geometryType += "Z"; + dimension = 3; } else if (hasM) { geometryType += "M"; + dimension = 3; } } } @@ -210,35 +233,74 @@ public boolean hasZ() { return hasZ; } + /** + * Set SFS type code + * @param sfs_geometryTypeCode + */ + public void setSfs_geometryTypeCode(int sfs_geometryTypeCode) { + this.sfs_geometryTypeCode = sfs_geometryTypeCode; + } + + /** + * Get SFS type code + * @return + */ public String getSfs_geometryType() { return sfs_geometryType; } + /** + * Set the dimension of the geometry + * @param dimension + */ public void setDimension(int dimension) { this.dimension = dimension; } + /** + * Set full geometry type with +1000 + * @param geometryTypeCode + */ public void setGeometryTypeCode(int geometryTypeCode) { this.geometryTypeCode = geometryTypeCode; this.sfs_geometryTypeCode = geometryTypeCode % 1_000; } + /** + * Set the geometry type name + * @param geometryType + */ public void setGeometryType(String geometryType) { this.geometryType = geometryType; } + /** + * Set the SRID + * @param SRID + */ public void setSRID(int SRID) { this.SRID = SRID; } + /** + * Set the SFS geometry type name + * @param sfs_geometryType + */ public void setSfs_geometryType(String sfs_geometryType) { this.sfs_geometryType = sfs_geometryType; } + /** + * True is geometry has M + * @param hasM + */ public void setHasM(boolean hasM) { this.hasM = hasM; } - + /** + * True is geometry has Z + * @param hasZ + */ public void setHasZ(boolean hasZ) { this.hasZ = hasZ; } @@ -262,13 +324,38 @@ public String getSQL() { /** * Read the first bytes of Geometry WKB. - * + * Note this method read the SRID from the EWKB mask + * It's better to use getMetaData(geometry) to get all metadata * @param bytes WKB Bytes * @return Geometry MetaData + * @throws IOException If WKB meta is invalid (do not check the Geometry) */ - public static GeometryMetaData getMetaData(byte[] bytes) { - ValueGeometry valueGeometry = ValueGeometry.get(bytes); - return new GeometryMetaData(valueGeometry); + public static GeometryMetaData getMetaData(byte[] bytes) { + try { + ByteOrderDataInStream dis = new ByteOrderDataInStream(); + dis.setInStream(new ByteArrayInStream(bytes)); + // determine byte order + byte byteOrderWKB = dis.readByte(); + // always set byte order, since it may change from geometry to geometry + int byteOrder = byteOrderWKB == WKBConstants.wkbNDR ? ByteOrderValues.LITTLE_ENDIAN : ByteOrderValues.BIG_ENDIAN; + dis.setOrder(byteOrder); + int typeInt = dis.readInt(); + int geometryType = typeInt & 0xff; + //From H2 + boolean hasZ = (typeInt & EWKB_Z) != 0; + boolean hasM = (typeInt & EWKB_M) != 0; + int srid = (typeInt & EWKB_SRID) != 0 ? dis.readInt() : 0; + GeometryMetaData geomMet = new GeometryMetaData(); + geomMet.setHasM(hasM); + geomMet.setHasZ(hasZ); + geomMet.setSRID(srid); + geomMet.setSfs_geometryTypeCode(geometryType); + geomMet.initGeometryType(); + + return geomMet; + }catch (IOException ex) { + throw new RuntimeException("Cannot read the geometry metadata"); + } } /** @@ -324,7 +411,6 @@ public static GeometryMetaData getMetaData(String geometry) { * as defined in SQL/MM specification. SQL-MM 3: 5.1.4 and OGC SFS 1.2 * * @param type : geometry type - * @param srid : srid value * @return GeometryMetaData */ private static GeometryMetaData createMetadataFromGeometryType(String type) { From 7f54324beae88e9ab2d759c3281166799b4a2992 Mon Sep 17 00:00:00 2001 From: ebocher Date: Tue, 9 Jun 2020 11:33:51 +0200 Subject: [PATCH 2/2] Stupid copy paste --- .../org/h2gis/functions/io/shp/SHPImportExportTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/h2gis-functions/src/test/java/org/h2gis/functions/io/shp/SHPImportExportTest.java b/h2gis-functions/src/test/java/org/h2gis/functions/io/shp/SHPImportExportTest.java index b98bef8138..346a565a79 100644 --- a/h2gis-functions/src/test/java/org/h2gis/functions/io/shp/SHPImportExportTest.java +++ b/h2gis-functions/src/test/java/org/h2gis/functions/io/shp/SHPImportExportTest.java @@ -837,10 +837,10 @@ public void exportImportPointPostGIS() throws SQLException, IOException { @Disabled @Test public void testSelectWriteReadPostGIS() throws Exception { - String url = "jdbc:postgresql://149.202.221.161:5432/?"; + String url = "jdbc:postgresql://?/?"; Properties props = new Properties(); - props.setProperty("user", "erwan"); - props.setProperty("password", "th@l@ss@56"); + props.setProperty("user", ""); + props.setProperty("password","" ); props.setProperty("url", url); DataSourceFactory dataSourceFactory = new DataSourceFactoryImpl(); DataSource ds = dataSourceFactory.createDataSource(props);