/**
* H2GIS is a library that brings spatial support to the H2 Database Engine
* <http://www.h2database.com>. H2GIS is developed by CNRS
* <http://www.cnrs.fr/>.
*
* 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 <http://www.gnu.org/licenses/>.
*
*
* For more information, please consult: <http://www.h2gis.org/>
* or contact directly: info_at_h2gis.org
*/
package org.h2gis.functions.spatial.type;
import org.h2gis.functions.spatial.properties.ColumnSRID;
import org.h2gis.functions.spatial.type.DimensionFromConstraint;
import org.h2gis.functions.factory.H2GISDBFactory;
import org.h2gis.utilities.GeometryTypeCodes;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.h2gis.utilities.SFSUtilities;
import org.h2gis.utilities.TableLocation;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Test constraints functions
* @author Nicolas Fortin
*/
public class ConstraintTest {
private static Connection connection;
@BeforeClass
public static void tearUp() throws Exception {
// Keep a connection alive to not close the DataBase on each unit test
connection = H2GISDBFactory.createSpatialDataBase("ConstraintTest");
}
@AfterClass
public static void tearDown() throws Exception {
connection.close();
}
/**
* LineString into Geometry column
* @throws Exception
*/
@Test
public void LineStringInGeometry() throws Exception {
Statement st = connection.createStatement();
st.execute("drop table test IF EXISTS");
st.execute("create table test (the_geom GEOMETRY)");
st.execute("insert into test values (ST_LineFromText('LINESTRING( 0 18, 10 21, 16 23, 28 26, 44 31 )' ,101))");
ResultSet rs = st.executeQuery("SELECT count(*) FROM test");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
}
/**
* LineString into LineString column
* @throws Exception
*/
@Test
public void LineStringInLineString() throws Exception {
Statement st = connection.createStatement();
st.execute("drop table test IF EXISTS");
st.execute("create table test (the_geom LINESTRING)");
st.execute("insert into test values (ST_LineFromText('LINESTRING( 0 18, 10 21, 16 23, 28 26, 44 31 )' ,101))");
ResultSet rs = st.executeQuery("SELECT count(*) FROM test");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
}
/**
* LineString into Point column
* @throws Exception
*/
@Test(expected = SQLException.class)
public void LineStringInPoint() throws Exception {
Statement st = connection.createStatement();
st.execute("drop table test IF EXISTS");
st.execute("create table test (the_geom POINT)");
st.execute("insert into test values (ST_LineFromText('LINESTRING( 0 18, 10 21, 16 23, 28 26, 44 31 )' ,101))");
}
/**
* LineString into LineString column
* @throws Exception
*/
@Test
public void testGeometryColumnsView() throws Exception {
Statement st = connection.createStatement();
st.execute("drop table T_GEOMETRY IF EXISTS");
st.execute("create table T_GEOMETRY (the_geom GEOMETRY)");
st.execute("drop table T_POINT IF EXISTS");
st.execute("create table T_POINT (the_geom POINT)");
st.execute("drop table T_LINE IF EXISTS");
st.execute("create table T_LINE (the_geom LINESTRING)");
st.execute("drop table T_POLYGON IF EXISTS");
st.execute("create table T_POLYGON (the_geom POLYGON)");
st.execute("drop table T_MPOINT IF EXISTS");
st.execute("create table T_MPOINT (the_geom MULTIPOINT)");
st.execute("drop table T_MLINE IF EXISTS");
st.execute("create table T_MLINE (the_geom MULTILINESTRING)");
st.execute("drop table T_MPOLYGON IF EXISTS");
st.execute("create table T_MPOLYGON (the_geom MULTIPOLYGON)");
ResultSet rs = st.executeQuery("select * from GEOMETRY_COLUMNS where F_TABLE_NAME in ('T_GEOMETRY','T_POINT','T_LINE','T_POLYGON','T_MGEOMETRY','T_MPOINT','T_MLINE','T_MPOLYGON') ORDER BY F_TABLE_NAME");
assertTrue(rs.next());
assertEquals("T_GEOMETRY",rs.getString("F_TABLE_NAME"));
assertEquals(GeometryTypeCodes.GEOMETRY,rs.getInt("geometry_type"));
assertTrue(rs.next());
assertEquals("T_LINE",rs.getString("F_TABLE_NAME"));
assertEquals(GeometryTypeCodes.LINESTRING,rs.getInt("geometry_type"));
assertTrue(rs.next());
assertEquals("T_MLINE",rs.getString("F_TABLE_NAME"));
assertEquals(GeometryTypeCodes.MULTILINESTRING,rs.getInt("geometry_type"));
assertTrue(rs.next());
assertEquals("T_MPOINT",rs.getString("F_TABLE_NAME"));
assertEquals(GeometryTypeCodes.MULTIPOINT,rs.getInt("geometry_type"));
assertTrue(rs.next());
assertEquals("T_MPOLYGON",rs.getString("F_TABLE_NAME"));
assertEquals(GeometryTypeCodes.MULTIPOLYGON,rs.getInt("geometry_type"));
assertTrue(rs.next());
assertEquals("T_POINT",rs.getString("F_TABLE_NAME"));
assertEquals(GeometryTypeCodes.POINT,rs.getInt("geometry_type"));
assertTrue(rs.next());
assertEquals("T_POLYGON",rs.getString("F_TABLE_NAME"));
assertEquals(GeometryTypeCodes.POLYGON,rs.getInt("geometry_type"));
assertFalse(rs.next());
st.execute("drop table T_GEOMETRY, T_POINT, T_LINE, T_POLYGON");
st.execute("drop table T_MPOINT, T_MLINE, T_MPOLYGON");
}
@Test
public void testSRIDConstraintExtraction() {
assertEquals(23, ColumnSRID.getSRIDFromConstraint("ST_SRID(the_geom)=23", "the_geom"));
assertEquals(23, ColumnSRID.getSRIDFromConstraint("ST_SRID(\"the_GEOM\") =23", "the_geom"));
assertEquals(23, ColumnSRID.getSRIDFromConstraint("ST_SRID(`the_GEOM`)= 23", "the_geom"));
assertEquals(23, ColumnSRID.getSRIDFromConstraint("GEOMETRY_TYPE = \"POLYGON\" AND ST_SRID ( the_geom ) = 23", "the_geom"));
assertEquals(0, ColumnSRID.getSRIDFromConstraint("ST_SRID(the_geom)=23", "geom")); //wrong column name
// two srid constraint on the same column
assertEquals(0, ColumnSRID.getSRIDFromConstraint("ST_SRID(geom)=44 OR ST_SRID(geom)=23", "geom"));
assertEquals(44, ColumnSRID.getSRIDFromConstraint("ST_SRID(the_geom)=23 AND ST_SRID(geom)=44", "geom"));
}
/**
* Check constraint violation
* @throws SQLException
*/
@Test(expected = SQLException.class)
public void testWrongSRID() throws SQLException {
Statement st = connection.createStatement();
try {
st.execute("drop table IF EXISTS T_SRID");
st.execute("create table T_SRID (the_geom GEOMETRY)");
st.execute("alter table t_srid ADD CONSTRAINT SRIDCONSTR CHECK ST_SRID(the_geom) = 27572");
} catch (SQLException ex) {
return;
}
st.execute("insert into T_SRID values('POINT(1 1)')");
}
/**
* Check constraint pass
* @throws SQLException
*/
@Test
public void testGoodSRID() throws SQLException {
Statement st = connection.createStatement();
st.execute("drop table IF EXISTS T_SRID");
st.execute("create table T_SRID (the_geom GEOMETRY)");
st.execute("alter table t_srid ADD CONSTRAINT SRIDCONSTR CHECK ST_SRID(the_geom) = 27572");
st.execute("insert into T_SRID values(ST_GeomFromText('POINT(1 1)', 27572))");
}
/**
* Check constraint pass
* @throws SQLException
*/
@Test
public void testTableSRIDGeometryColumns() throws SQLException {
Statement st = connection.createStatement();
st.execute("drop table IF EXISTS T_SRID");
st.execute("create table T_SRID (the_geom GEOMETRY)");
ResultSet rs = st.executeQuery("SELECT SRID FROM GEOMETRY_COLUMNS WHERE F_TABLE_NAME = 'T_SRID'");
assertTrue(rs.next());
assertEquals(0, rs.getInt("srid"));
assertFalse(rs.next());
rs.close();
// Check 0 in srid
st.execute("alter table t_srid ADD CONSTRAINT SRIDCONSTR CHECK ST_SRID(the_geom) = 27572");
// Check 27572 in srid
rs = st.executeQuery("SELECT SRID FROM GEOMETRY_COLUMNS WHERE F_TABLE_NAME = 'T_SRID'");
assertTrue(rs.next());
assertEquals(27572, rs.getInt("srid"));
assertFalse(rs.next());
rs.close();
}
/**
* Check constraint pass
* @throws SQLException
*/
@Test
public void testColumnSRIDGeometryColumns() throws SQLException {
Statement st = connection.createStatement();
st.execute("drop table IF EXISTS T_SRID");
st.execute("create table T_SRID (the_geom GEOMETRY CHECK ST_SRID(the_geom) = 27572)");
ResultSet rs = st.executeQuery("SELECT SRID FROM GEOMETRY_COLUMNS WHERE F_TABLE_NAME = 'T_SRID'");
assertTrue(rs.next());
assertEquals(27572, rs.getInt("srid"));
assertFalse(rs.next());
rs.close();
}
/**
* LineString into LineString column
* @throws Exception
*/
@Test
public void testGeometryColumnsName() throws Exception {
Statement st = connection.createStatement();
st.execute("drop table T_GEOMETRY IF EXISTS");
st.execute("create table T_GEOMETRY (the_geom GEOMETRY)");
st.execute("drop table T_POINT IF EXISTS");
st.execute("create table T_POINT (the_geom POINT)");
st.execute("drop table T_LINE IF EXISTS");
st.execute("create table T_LINE (the_geom LINESTRING)");
st.execute("drop table T_POLYGON IF EXISTS");
st.execute("create table T_POLYGON (the_geom POLYGON)");
st.execute("drop table T_MPOINT IF EXISTS");
st.execute("create table T_MPOINT (the_geom MULTIPOINT)");
st.execute("drop table T_MLINE IF EXISTS");
st.execute("create table T_MLINE (the_geom MULTILINESTRING)");
st.execute("drop table T_MPOLYGON IF EXISTS");
st.execute("create table T_MPOLYGON (the_geom MULTIPOLYGON)");
ResultSet rs = st.executeQuery("select * from GEOMETRY_COLUMNS where f_table_name IN ('T_GEOMETRY', 'T_POINT'," +
" 'T_LINE', 'T_POLYGON','T_MPOINT','T_MLINE', 'T_MPOLYGON') order by f_table_name");
try {
assertTrue(rs.next());
assertEquals("GEOMETRY", rs.getString("type"));
assertTrue(rs.next());
assertEquals("LINESTRING", rs.getString("type"));
assertTrue(rs.next());
assertEquals("MULTILINESTRING", rs.getString("type"));
assertTrue(rs.next());
assertEquals("MULTIPOINT", rs.getString("type"));
assertTrue(rs.next());
assertEquals("MULTIPOLYGON", rs.getString("type"));
assertTrue(rs.next());
assertEquals("POINT", rs.getString("type"));
assertTrue(rs.next());
assertEquals("POLYGON", rs.getString("type"));
assertFalse(rs.next());
} finally {
rs.close();
}
st.execute("drop table T_GEOMETRY, T_POINT, T_LINE, T_POLYGON");
st.execute("drop table T_MPOINT, T_MLINE, T_MPOLYGON");
}
/**
* LineString into LineString column
* @throws Exception
*/
@Test
public void testGeometryColumnsViewUtility() throws Exception {
Statement st = connection.createStatement();
st.execute("drop table T_GEOMETRY IF EXISTS");
st.execute("create table T_GEOMETRY (the_geom GEOMETRY)");
st.execute("drop table T_POINT IF EXISTS");
st.execute("create table T_POINT (the_geom POINT)");
st.execute("drop table T_LINE IF EXISTS");
st.execute("create table T_LINE (the_geom LINESTRING)");
st.execute("drop table T_POLYGON IF EXISTS");
st.execute("create table T_POLYGON (the_geom POLYGON)");
st.execute("drop table T_MPOINT IF EXISTS");
st.execute("create table T_MPOINT (the_geom MULTIPOINT)");
st.execute("drop table T_MLINE IF EXISTS");
st.execute("create table T_MLINE (the_geom MULTILINESTRING)");
st.execute("drop table T_MPOLYGON IF EXISTS");
st.execute("create table T_MPOLYGON (the_geom MULTIPOLYGON)");
assertEquals(GeometryTypeCodes.GEOMETRY,
SFSUtilities.getGeometryType(connection, TableLocation.parse("T_GEOMETRY"),""));
assertEquals(GeometryTypeCodes.LINESTRING,
SFSUtilities.getGeometryType(connection, TableLocation.parse("T_LINE"),""));
assertEquals(GeometryTypeCodes.POLYGON,
SFSUtilities.getGeometryType(connection, TableLocation.parse("T_POLYGON"),""));
assertEquals(GeometryTypeCodes.POINT,
SFSUtilities.getGeometryType(connection, TableLocation.parse("T_POINT"),""));
assertEquals(GeometryTypeCodes.MULTILINESTRING,
SFSUtilities.getGeometryType(connection, TableLocation.parse("T_MLINE"),""));
assertEquals(GeometryTypeCodes.MULTIPOLYGON,
SFSUtilities.getGeometryType(connection, TableLocation.parse("T_MPOLYGON"),""));
assertEquals(GeometryTypeCodes.MULTIPOINT,
SFSUtilities.getGeometryType(connection, TableLocation.parse("T_MPOINT"),""));
st.execute("drop table T_GEOMETRY, T_POINT, T_LINE, T_POLYGON");
st.execute("drop table T_MPOINT, T_MLINE, T_MPOLYGON");
}
@Test
public void testZConstraintOk() throws SQLException {
Statement st = connection.createStatement();
st.execute("drop table LIDAR_PTS IF EXISTS");
st.execute("create table LIDAR_PTS (the_geom POINT CHECK ST_COORDDIM(the_geom) = 3)");
st.execute("insert into LIDAR_PTS VALUES ('POINT(12 14 56)')");
st.execute("drop table LIDAR_PTS IF EXISTS");
}
@Test(expected = SQLException.class)
public void testZConstraintError() throws SQLException {
Statement st = connection.createStatement();
st.execute("drop table LIDAR_PTS IF EXISTS");
st.execute("create table LIDAR_PTS (the_geom POINT CHECK ST_COORDDIM(the_geom) = 3)");
st.execute("insert into LIDAR_PTS VALUES ('POINT(12 14)')");
st.execute("insert into LIDAR_PTS VALUES ('POINT(13 18)')");
st.execute("drop table LIDAR_PTS IF EXISTS");
}
@Test
public void testDimensionFromConstraint() {
assertEquals(3, DimensionFromConstraint.dimensionFromConstraint("ST_COORDDIM(the_geom) = 3", "the_geom"));
assertEquals(3, DimensionFromConstraint.dimensionFromConstraint("ST_COORDDIM(the_geom) > 2", "the_geom"));
assertEquals(2, DimensionFromConstraint.dimensionFromConstraint("ST_COORDDIM(the_geom) < 3", "the_geom"));
assertEquals(2, DimensionFromConstraint.dimensionFromConstraint("ST_COORDDIM( the_geom )!= 3", "the_geom"));
assertEquals(2, DimensionFromConstraint.dimensionFromConstraint("ST_COORDDIM( the_geom )<> 3", "the_geom"));
assertEquals(3, DimensionFromConstraint.dimensionFromConstraint("ST_COORDDIM(`the_geom`)> 2", "the_geom"));
assertEquals(3, DimensionFromConstraint.dimensionFromConstraint("ST_COORDDIM(\"the_geom\")!= 2", "the_geom"));
assertEquals(2, DimensionFromConstraint.dimensionFromConstraint("ST_COORDDIM(\"geom\")= 3", "the_geom"));
}
@Test
public void testGeometryColumnCoordDimension() throws SQLException {
Statement st = connection.createStatement();
st.execute("drop table T_GEOMETRY2D IF EXISTS");
st.execute("drop table T_GEOMETRY3D IF EXISTS");
st.execute("create table T_GEOMETRY2D (the_geom GEOMETRY)");
st.execute("alter table T_GEOMETRY2D add constraint zconstr CHECK ST_COORDDIM(the_geom) = 2");
st.execute("create table T_GEOMETRY3D (the_geom GEOMETRY CHECK ST_COORDDIM(the_geom) = 3)");
ResultSet rs = st.executeQuery("SELECT * FROM GEOMETRY_COLUMNS WHERE F_TABLE_NAME IN ('T_GEOMETRY2D','T_GEOMETRY3D') ORDER BY F_TABLE_NAME");
try {
assertTrue(rs.next());
assertEquals("T_GEOMETRY2D", rs.getString("F_TABLE_NAME"));
assertEquals(2, rs.getInt("COORD_DIMENSION"));
assertTrue(rs.next());
assertEquals("T_GEOMETRY3D", rs.getString("F_TABLE_NAME"));
assertEquals(3, rs.getInt("COORD_DIMENSION"));
assertFalse(rs.next());
} finally {
rs.close();
}
}
}