/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2015, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.jdbc; import java.io.IOException; import java.sql.Connection; import java.sql.Date; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import org.geotools.data.*; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.feature.NameImpl; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.referencing.CRS; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.feature.type.AttributeType; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.io.WKTReader; /** * * * @source $URL$ */ public abstract class JDBCDataStoreOnlineTest extends JDBCTestSupport { public void testGetNames() throws IOException { String[] typeNames = dataStore.getTypeNames(); assertTrue(new HashSet(Arrays.asList(typeNames)).contains(tname("ft1"))); } public void testGetSchema() throws Exception { SimpleFeatureType ft1 = dataStore.getSchema(tname("ft1")); assertNotNull(ft1); assertNotNull(ft1.getDescriptor(aname("geometry"))); assertNotNull(ft1.getDescriptor(aname("intProperty"))); assertNotNull(ft1.getDescriptor(aname("doubleProperty"))); assertNotNull(ft1.getDescriptor(aname("stringProperty"))); assertTrue(Geometry.class.isAssignableFrom(ft1.getDescriptor(aname("geometry")).getType() .getBinding())); assertTrue(Number.class.isAssignableFrom( ft1.getDescriptor(aname("intProperty")).getType().getBinding()) ); assertEquals(Double.class, ft1.getDescriptor(aname("doubleProperty")).getType().getBinding()); assertEquals(String.class, ft1.getDescriptor(aname("stringProperty")).getType().getBinding()); } public void testCreateSchema() throws Exception { SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName(tname("ft2")); builder.setNamespaceURI(dataStore.getNamespaceURI()); builder.setCRS(CRS.decode("EPSG:4326")); builder.add(aname("geometry"), Geometry.class); builder.add(aname("intProperty"), Integer.class); builder.add(aname("dateProperty"), Date.class); SimpleFeatureType featureType = builder.buildFeatureType(); dataStore.createSchema(featureType); SimpleFeatureType ft2 = dataStore.getSchema(tname("ft2")); //JD: making the comparison a bit more lax //asertEquals(ft2,featureType); assertEqualsLax(ft2,featureType); //TODO: we should also check the crs as well //assertTrue(CRS.equalsIgnoreMetadata(featureType.getCoordinateReferenceSystem(), // ft2.getCoordinateReferenceSystem())); // GEOT-2031 assertNotSame(ft2, featureType); StringBuffer sql = new StringBuffer(); sql.append("SELECT * FROM "); if (dataStore.getDatabaseSchema() != null) { dataStore.getSQLDialect().encodeSchemaName(dataStore.getDatabaseSchema(), sql); sql.append("."); } dataStore.getSQLDialect().encodeTableName("ft2", sql); try(Connection cx = dataStore.createConnection(); Statement st = cx.createStatement(); ResultSet rs = st.executeQuery(sql.toString())) { } catch (SQLException e) { throw e; } } public void testCreateSchemaWithConstraints() throws Exception { SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName(tname("ft2")); builder.setNamespaceURI(dataStore.getNamespaceURI()); builder.setCRS(CRS.decode("EPSG:4326")); builder.add(aname("geometry"), Geometry.class); builder.nillable(false).add(aname("intProperty"), Integer.class); builder.length(5).add(aname("stringProperty"), String.class); SimpleFeatureType featureType = builder.buildFeatureType(); dataStore.createSchema(featureType); SimpleFeatureType ft2 = dataStore.getSchema(tname("ft2")); //assertEquals(ft2, featureType); //grab a writer try(FeatureWriter<SimpleFeatureType, SimpleFeature> w = dataStore.getFeatureWriter( tname("ft2"),Transaction.AUTO_COMMIT)) { w.hasNext(); SimpleFeature f = w.next(); f.setAttribute( 1, new Integer(0)); f.setAttribute( 2, "hello"); w.write(); w.hasNext(); f = w.next(); f.setAttribute( 1, null ); try { w.write(); fail( "null value for intProperty should have failed"); } catch( Exception e ) { } f.setAttribute( 1, new Integer(1) ); f.setAttribute( 2, "hello!"); try { w.write(); fail( "string greather than 5 chars should have failed"); } catch( Exception e ) { } } } public void testRemoveSchema() throws Exception { SimpleFeatureType ft = dataStore.getSchema(tname("ft1")); assertNotNull(ft); dataStore.removeSchema(tname("ft1")); try { dataStore.getSchema(tname("ft1")); fail("getSchema() should fail if table was deleted"); } catch(Exception e) { } } public void testSimpleIndex() throws Exception { SimpleFeatureType ft = dataStore.getSchema(tname("ft1")); assertNotNull(ft); // check initial status String ft1TypeName = ft.getTypeName(); List<Index> indexes = dataStore.getIndexes(ft1TypeName); assertNotNull(indexes); final int initialSize = indexes.size(); // create index String indexName = "ft1_str_index"; Index stringIndex = new Index(ft1TypeName, indexName, false, aname("stringProperty")); dataStore.createIndex(stringIndex); // check the index has been created indexes = dataStore.getIndexes(ft1TypeName); assertEquals(initialSize + 1, indexes.size()); for (Index index : indexes) { assertEquals(ft1TypeName, index.getTypeName()); if(index.getIndexName().equals(indexName)) { List<String> attributes = index.getAttributes(); assertEquals(1, attributes.size()); assertEquals(aname("stringProperty"), attributes.get(0)); assertFalse(index.isUnique()); } } // drop it dataStore.dropIndex(ft1TypeName, indexName); indexes = dataStore.getIndexes(ft1TypeName); assertEquals(initialSize, indexes.size()); for (Index index : indexes) { assertEquals(ft1TypeName, index.getTypeName()); if(index.getIndexName().equals(indexName)) { fail("the index has not been removed"); } } } public void testMultiColumnIndex() throws Exception { SimpleFeatureType ft = dataStore.getSchema(tname("ft1")); assertNotNull(ft); // check initial status String ft1TypeName = ft.getTypeName(); List<Index> indexes = dataStore.getIndexes(ft1TypeName); assertNotNull(indexes); final int initialSize = indexes.size(); // create index String indexName = "ft1_str_index"; Index stringIndex = new Index(ft1TypeName, indexName, false, aname("stringProperty"), aname("intProperty")); dataStore.createIndex(stringIndex); // check the index has been created indexes = dataStore.getIndexes(ft1TypeName); assertEquals(initialSize + 1, indexes.size()); for (Index index : indexes) { assertEquals(ft1TypeName, index.getTypeName()); if(index.getIndexName().equals(indexName)) { List<String> attributes = index.getAttributes(); assertEquals(2, attributes.size()); assertEquals(aname("stringProperty"), attributes.get(0)); assertEquals(aname("intProperty"), attributes.get(1)); } } // drop it dataStore.dropIndex(ft1TypeName, indexName); indexes = dataStore.getIndexes(ft1TypeName); assertEquals(initialSize, indexes.size()); for (Index index : indexes) { assertEquals(ft1TypeName, index.getTypeName()); if(index.getIndexName().equals(indexName)) { fail("the index has not been removed"); } } } public void testCreateSchemaUTMCRS() throws Exception { SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName(tname("ft2")); builder.setNamespaceURI(dataStore.getNamespaceURI()); builder.setCRS(CRS.decode("EPSG:26713")); builder.add(aname("geometry"), Point.class); builder.add(aname("intProperty"), Integer.class); builder.add(aname("stringProperty"), String.class); SimpleFeatureType featureType = builder.buildFeatureType(); dataStore.createSchema(featureType); SimpleFeatureType ft2 = dataStore.getSchema(tname("ft2")); assertNotNull(ft2); try(FeatureWriter w = dataStore.getFeatureWriter( tname("ft2"),Transaction.AUTO_COMMIT)) { w.hasNext(); //write out a feature with a geomety in teh srs, basically accomodate databases that have // to query the first feature in order to get the srs for the feature type SimpleFeature f = (SimpleFeature) w.next(); Geometry g = new WKTReader().read("POINT(593493 4914730)"); g.setSRID(26713); f.setAttribute(0, g); f.setAttribute( 1, new Integer(0)); f.setAttribute( 2, "hello"); w.write(); } //clear out the feature type cache dataStore.getEntry(new NameImpl(dataStore.getNamespaceURI(), tname("ft2"))).dispose(); ft2 = dataStore.getSchema(tname("ft2")); assertTrue(CRS.equalsIgnoreMetadata(CRS.decode("EPSG:26713"), ft2.getCoordinateReferenceSystem())); } public void testCreateSchemaFidColumn() throws Exception { //test a case where the feature type we are creating contains a column named "fid" SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName(tname("ft2")); builder.setNamespaceURI(dataStore.getNamespaceURI()); builder.setCRS(CRS.decode("EPSG:26713")); builder.add(aname("geometry"), Point.class); builder.add(aname("intProperty"), Integer.class); builder.add(aname("stringProperty"), String.class); builder.add(aname("fid"), String.class); SimpleFeatureType featureType = builder.buildFeatureType(); dataStore.createSchema(featureType); SimpleFeatureType ft2 = dataStore.getSchema(tname("ft2")); assertNotNull(ft2.getDescriptor(aname("fid"))); } void assertEqualsLax( SimpleFeatureType e, SimpleFeatureType a ) { if ( e.equals( a ) ) { return; } //do a lax check assertEquals( e.getAttributeCount(), a.getAttributeCount() ); for ( int i = 0; i < e.getAttributeCount(); i++ ) { AttributeDescriptor att1 = e.getDescriptor( i ); AttributeDescriptor att2 = a.getDescriptor( i ); assertEquals( att1.getName(), att2.getName() ); assertEquals( att1.getMinOccurs(), att2.getMinOccurs() ); assertEquals( att1.getMaxOccurs(), att2.getMaxOccurs() ); assertEquals( att1.isNillable(), att2.isNillable() ); assertEquals( att1.getDefaultValue(), att2.getDefaultValue() ); AttributeType t1 = att1.getType(); AttributeType t2 = att2.getType(); assertEquals( t1.getName(), t2.getName() ); assertEquals( t1.getDescription(), t2.getDescription() ); assertEquals( t1.getRestrictions(), t2.getRestrictions() ); //be a bit lax on type mappings if (!t1.getBinding().equals( t2.getBinding() ) ) { if ( Number.class.isAssignableFrom( t1.getBinding() ) ) { assertTrue( Number.class.isAssignableFrom( t2.getBinding() ) ); } if ( Date.class.isAssignableFrom( t2.getBinding() ) ) { assertTrue( Date.class.isAssignableFrom( t2.getBinding() ) ); } } } } public void testGetFeatureSource() throws Exception { SimpleFeatureSource featureSource = dataStore.getFeatureSource(tname("ft1")); assertNotNull(featureSource); } public void testGetFeatureReader() throws Exception { final GeometryFactory gf = dataStore.getGeometryFactory(); Query query = new Query(tname("ft1")); try(FeatureReader<SimpleFeatureType, SimpleFeature> reader = dataStore.getFeatureReader(query, Transaction.AUTO_COMMIT)) { assertFeatureReader(0, 3, reader, new SimpleFeatureAssertion() { public int toIndex(SimpleFeature feature) { return ((Number) feature.getAttribute(aname("intProperty"))).intValue(); } public void check(int index, SimpleFeature feature) { assertEquals(4, feature.getAttributeCount()); Point p = gf.createPoint(new Coordinate(index, index)); assertTrue(p.equalsExact((Geometry) feature.getAttribute(aname("geometry")))); Number ip = (Number) feature.getAttribute(aname("intProperty")); assertEquals(index, ip.intValue()); } }); } query.setPropertyNames(new String[] { aname("intProperty") }); try(FeatureReader<SimpleFeatureType, SimpleFeature> reader = dataStore.getFeatureReader(query, Transaction.AUTO_COMMIT)) { for (int i = 0; i < 3; i++) { assertTrue(reader.hasNext()); SimpleFeature feature = reader.next(); assertEquals(1, feature.getAttributeCount()); } assertFalse(reader.hasNext()); } FilterFactory ff = dataStore.getFilterFactory(); Filter f = ff.equals(ff.property(aname("intProperty")), ff.literal(1)); query.setFilter(f); try(FeatureReader<SimpleFeatureType, SimpleFeature> reader = dataStore.getFeatureReader(query, Transaction.AUTO_COMMIT)) { for (int i = 0; i < 1; i++) { assertTrue(reader.hasNext()); SimpleFeature feature = reader.next(); } assertFalse(reader.hasNext()); } } public void testGetFeatureWriter() throws IOException { try(FeatureWriter<SimpleFeatureType, SimpleFeature> writer = dataStore.getFeatureWriter(tname("ft1"), Transaction.AUTO_COMMIT)) { while (writer.hasNext()) { SimpleFeature feature = writer.next(); feature.setAttribute(aname("stringProperty"), "foo"); writer.write(); } } Query query = new Query(tname("ft1")); try(FeatureReader<SimpleFeatureType, SimpleFeature> reader = dataStore.getFeatureReader(query, Transaction.AUTO_COMMIT)) { assertTrue(reader.hasNext()); while (reader.hasNext()) { SimpleFeature feature = reader.next(); assertEquals("foo", feature.getAttribute(aname("stringProperty"))); } } } public void testGetFeatureWriterWithFilter() throws IOException { FilterFactory ff = dataStore.getFilterFactory(); Filter f = ff.equals(ff.property(aname("intProperty")), ff.literal(100)); SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ft1")).getFeatures(f); assertEquals(0, features.size()); f = ff.equals(ff.property(aname("intProperty")), ff.literal(1)); try(FeatureWriter<SimpleFeatureType, SimpleFeature> writer = dataStore.getFeatureWriter(tname("ft1"), f, Transaction.AUTO_COMMIT)) { while (writer.hasNext()) { SimpleFeature feature = writer.next(); feature.setAttribute(aname("intProperty"), new Integer(100)); writer.write(); } } f = ff.equals(ff.property(aname("intProperty")), ff.literal(100)); features = dataStore.getFeatureSource(tname("ft1")).getFeatures(f); assertEquals(1, features.size()); } public void testGetFeatureWriterAppend() throws IOException { try(FeatureWriter<SimpleFeatureType, SimpleFeature> writer = dataStore.getFeatureWriterAppend(tname("ft1"), Transaction.AUTO_COMMIT)) { for (int i = 3; i < 6; i++) { SimpleFeature feature = writer.next(); feature.setAttribute(aname("intProperty"), new Integer(i)); writer.write(); } } SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ft1")).getFeatures(); assertEquals(6, features.size()); } @Override protected HashMap createDataStoreFactoryParams() throws Exception { HashMap params = super.createDataStoreFactoryParams(); // This test expects the write to happen right away. Disable buffering. params.put(JDBCDataStoreFactory.BATCH_INSERT_SIZE.key, 1); return params; } }