Add stubs for PostGIS support #631

This commit is contained in:
Timo Westkämper 2014-02-03 22:50:46 +02:00
parent 8c1a4732da
commit 24e898c4e9
13 changed files with 359 additions and 66 deletions

View File

@ -88,7 +88,7 @@
<groupId>org.postgis</groupId>
<artifactId>postgis-jdbc</artifactId>
<version>1.3.3</version>
<scope>test</scope>
<scope>provided</scope>
</dependency>
<dependency>

View File

@ -47,9 +47,7 @@ public class PostgresTemplates extends SQLTemplates {
setDummyTable(null);
setCountDistinctMultipleColumns(true);
setCountViaAnalytics(true);
addSpatialOps(true);
// type mappings
addClass2TypeMappings("numeric(3,0)", Byte.class);
addClass2TypeMappings("double precision", Double.class);

View File

@ -13,11 +13,9 @@
*/
package com.mysema.query.sql;
import java.sql.Types;
import com.mysema.query.QueryMetadata;
import com.mysema.query.QueryModifiers;
import com.mysema.query.sql.spatial.GeometryWktType;
import com.mysema.query.sql.spatial.GeometryWktClobType;
import com.mysema.query.types.Ops;
@ -61,7 +59,7 @@ public class TeradataTemplates extends SQLTemplates {
setDummyTable(null);
setCountViaAnalytics(true);
addCustomType(new GeometryWktType(Types.CLOB));
addCustomType(GeometryWktClobType.DEFAULT);
addClass2TypeMappings("byteint", Byte.class);
addClass2TypeMappings("double precision", Double.class);
addClass2TypeMappings("varchar(4000)", String.class);

View File

@ -0,0 +1,155 @@
/*
* Copyright 2014, Mysema Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mysema.query.sql.postgres;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.GeometryCollection;
import org.geolatte.geom.GeometryFactory;
import org.geolatte.geom.LineString;
import org.geolatte.geom.MultiLineString;
import org.geolatte.geom.MultiPoint;
import org.geolatte.geom.MultiPolygon;
import org.geolatte.geom.Point;
import org.geolatte.geom.PolyHedralSurface;
import org.geolatte.geom.Polygon;
import org.postgis.LinearRing;
import org.postgis.PGgeometry;
/**
* @author tiwe
*
*/
public class PGGeometryConverter {
private GeometryFactory geometryFactory;
public static PGgeometry convert(Geometry geometry) {
if (geometry instanceof Point) {
return convert((Point)geometry);
} else if (geometry instanceof LineString) {
return convert((LineString)geometry);
} else if (geometry instanceof MultiLineString) {
return convert((MultiLineString)geometry);
} else if (geometry instanceof Polygon) {
return convert((Polygon)geometry);
} else if (geometry instanceof PolyHedralSurface) {
return convert((PolyHedralSurface)geometry);
} else if (geometry instanceof MultiPoint) {
return convert((MultiPoint)geometry);
} else if (geometry instanceof MultiPolygon) {
return convert((MultiPolygon)geometry);
} else if (geometry instanceof GeometryCollection) {
return convert((GeometryCollection)geometry);
} else {
throw new IllegalArgumentException(geometry.getClass().getName());
}
}
private static PGgeometry convert(Point point) {
point.get
return null; // TODO
}
private static PGgeometry convert(LineString lineString) {
return null; // TODO
}
private static PGgeometry convert(MultiLineString multiLineString) {
return null; // TODO
}
private static PGgeometry convert(Polygon polygon) {
return null; // TODO
}
private static PGgeometry convert(PolyHedralSurface polyHedralSurface) {
return null; // TODO
}
private static PGgeometry convert(MultiPoint multiPoint) {
return null; // TODO
}
private static PGgeometry convert(MultiPolygon multiPolygon) {
return null; // TODO
}
private static PGgeometry convert(GeometryCollection multiPolygon) {
return null; // TODO
}
public static Geometry convert(PGgeometry geometry) {
switch (geometry.getGeoType()) {
case org.postgis.Geometry.POINT:
return convert((org.postgis.Point)geometry.getGeometry());
case org.postgis.Geometry.LINESTRING:
return convert((org.postgis.LineString)geometry.getGeometry());
case org.postgis.Geometry.LINEARRING:
return convert((org.postgis.LinearRing)geometry.getGeometry());
case org.postgis.Geometry.POLYGON:
return convert((org.postgis.Polygon)geometry.getGeometry());
case org.postgis.Geometry.MULTILINESTRING:
return convert((org.postgis.MultiLineString)geometry.getGeometry());
case org.postgis.Geometry.MULTIPOINT:
return convert((org.postgis.MultiPoint)geometry.getGeometry());
case org.postgis.Geometry.MULTIPOLYGON:
return convert((org.postgis.MultiPolygon)geometry.getGeometry());
case org.postgis.Geometry.GEOMETRYCOLLECTION:
return convert((org.postgis.GeometryCollection)geometry.getGeometry());
}
throw new IllegalArgumentException(geometry.toString());
}
private static Geometry convert(org.postgis.GeometryCollection geometry) {
// TODO Auto-generated method stub
return null;
}
private static Geometry convert(org.postgis.MultiPolygon geometry) {
// TODO Auto-generated method stub
return null;
}
private static Geometry convert(org.postgis.MultiPoint geometry) {
// TODO Auto-generated method stub
return null;
}
private static Geometry convert(org.postgis.MultiLineString geometry) {
// TODO Auto-generated method stub
return null;
}
private static Geometry convert(org.postgis.Polygon geometry) {
// TODO Auto-generated method stub
return null;
}
private static Geometry convert(LinearRing geometry) {
// TODO Auto-generated method stub
return null;
}
private static Geometry convert(org.postgis.LineString geometry) {
// TODO Auto-generated method stub
return null;
}
private static Geometry convert(org.postgis.Point geometry) {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2014, Mysema Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mysema.query.sql.postgres;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import javax.annotation.Nullable;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkt;
import com.mysema.query.sql.types.AbstractType;
/**
* @author tiwe
*
*/
public class PGGeometryType extends AbstractType<Geometry> {
public static final PGGeometryType DEFAULT = new PGGeometryType();
public PGGeometryType() {
super(Types.STRUCT);
}
@Override
public Class<Geometry> getReturnedClass() {
return Geometry.class;
}
@Override
@Nullable
public Geometry getValue(ResultSet rs, int startIndex) throws SQLException {
String str = rs.getString(startIndex);
if (str != null) {
return Wkt.newWktDecoder(Wkt.Dialect.POSTGIS_EWKT_1).decode(str);
} else {
return null;
}
}
@Override
public void setValue(PreparedStatement st, int startIndex, Geometry value) throws SQLException {
String str = Wkt.newWktEncoder(Wkt.Dialect.POSTGIS_EWKT_1).encode(value);
st.setString(startIndex, str);
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright 2011, Mysema Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mysema.query.sql.postgres;
import com.mysema.query.sql.PostgresTemplates;
import com.mysema.query.sql.SQLTemplates;
/**
* @author tiwe
*
*/
public class PostGISTemplates extends PostgresTemplates {
public static Builder builder() {
return new Builder() {
@Override
protected SQLTemplates build(char escape, boolean quote) {
return new PostGISTemplates(escape, quote);
}
};
}
public PostGISTemplates() {
this('\\', false);
}
public PostGISTemplates(boolean quote) {
this('\\', quote);
}
public PostGISTemplates(char escape, boolean quote) {
super(escape, quote);
addSpatialOps(true);
}
}

View File

@ -22,6 +22,7 @@ import javax.annotation.Nullable;
import org.geolatte.geom.ByteBuffer;
import org.geolatte.geom.ByteOrder;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkb;
import org.geolatte.geom.codec.WkbDecoder;
import org.geolatte.geom.codec.WkbEncoder;
@ -33,16 +34,10 @@ import com.mysema.query.sql.types.AbstractType;
*/
public class GeometryWkbType extends AbstractType<Geometry> {
private final WkbEncoder encoder;
private final WkbDecoder decoder;
private final ByteOrder byteOrder;
public GeometryWkbType(int type, WkbEncoder encoder, WkbDecoder decoder, ByteOrder byteOrder) {
public GeometryWkbType(int type, ByteOrder byteOrder) {
super(type);
this.encoder = encoder;
this.decoder = decoder;
this.byteOrder = byteOrder;
}
@ -56,6 +51,7 @@ public class GeometryWkbType extends AbstractType<Geometry> {
public Geometry getValue(ResultSet rs, int startIndex) throws SQLException {
byte[] bytes = rs.getBytes(startIndex);
if (bytes != null) {
WkbDecoder decoder = Wkb.newWkbDecoder(Wkb.Dialect.POSTGIS_EWKB_1);
return decoder.decode(ByteBuffer.from(bytes));
} else {
return null;
@ -64,6 +60,7 @@ public class GeometryWkbType extends AbstractType<Geometry> {
@Override
public void setValue(PreparedStatement st, int startIndex, Geometry value) throws SQLException {
WkbEncoder encoder = Wkb.newWkbEncoder(Wkb.Dialect.POSTGIS_EWKB_1);
ByteBuffer buffer = encoder.encode(value, byteOrder);
st.setBytes(startIndex, buffer.toByteArray());
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 2014, Mysema Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mysema.query.sql.spatial;
import java.sql.Clob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import javax.annotation.Nullable;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkt;
import com.mysema.query.sql.types.AbstractType;
/**
* @author tiwe
*
*/
public class GeometryWktClobType extends AbstractType<Geometry> {
public static final GeometryWktClobType DEFAULT = new GeometryWktClobType();
public GeometryWktClobType() {
super(Types.CLOB);
}
@Override
public Class<Geometry> getReturnedClass() {
return Geometry.class;
}
@Override
@Nullable
public Geometry getValue(ResultSet rs, int startIndex) throws SQLException {
Clob clob = rs.getClob(startIndex);
String str = clob != null ? clob.getSubString(1, (int) clob.length()) : null;
if (str != null) {
return Wkt.newWktDecoder(Wkt.Dialect.POSTGIS_EWKT_1).decode(str);
} else {
return null;
}
}
@Override
public void setValue(PreparedStatement st, int startIndex, Geometry value) throws SQLException {
String str = Wkt.newWktEncoder(Wkt.Dialect.POSTGIS_EWKT_1).encode(value);
st.setString(startIndex, str);
}
}

View File

@ -13,7 +13,6 @@
*/
package com.mysema.query.sql.spatial;
import java.sql.Clob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@ -23,8 +22,6 @@ import javax.annotation.Nullable;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkt;
import org.geolatte.geom.codec.WktDecoder;
import org.geolatte.geom.codec.WktEncoder;
import com.mysema.query.sql.types.AbstractType;
@ -34,27 +31,10 @@ import com.mysema.query.sql.types.AbstractType;
*/
public class GeometryWktType extends AbstractType<Geometry> {
private static final WktEncoder<Geometry> ENCODER = Wkt.newWktEncoder(Wkt.Dialect.POSTGIS_EWKT_1);
public static final GeometryWktType DEFAULT = new GeometryWktType();
private static final WktDecoder<Geometry> DECODER = Wkt.newWktDecoder(Wkt.Dialect.POSTGIS_EWKT_1);
public static final GeometryWktType DEFAULT = new GeometryWktType(Types.VARCHAR, ENCODER, DECODER);
private final int type;
private final WktEncoder<Geometry> encoder;
private final WktDecoder<Geometry> decoder;
public GeometryWktType(int type) {
this(type, ENCODER, DECODER);
}
public GeometryWktType(int type, WktEncoder<Geometry> encoder, WktDecoder<Geometry> decoder) {
super(type);
this.type = type;
this.encoder = encoder;
this.decoder = decoder;
public GeometryWktType() {
super(Types.VARCHAR);
}
@Override
@ -65,29 +45,18 @@ public class GeometryWktType extends AbstractType<Geometry> {
@Override
@Nullable
public Geometry getValue(ResultSet rs, int startIndex) throws SQLException {
String str;
if (type == Types.VARCHAR) {
str = rs.getString(startIndex);
} else if (type == Types.CLOB) {
Clob clob = rs.getClob(startIndex);
str = clob != null ? clob.getSubString(1, (int) clob.length()) : null;
String str = rs.getString(startIndex);
if (str != null) {
return Wkt.newWktDecoder(Wkt.Dialect.POSTGIS_EWKT_1).decode(str);
} else {
throw new IllegalStateException("Unsupported type " + type);
return null;
}
return str != null ? decoder.decode(str) : null;
}
@Override
public void setValue(PreparedStatement st, int startIndex, Geometry value) throws SQLException {
String str = encoder.encode(value);
if (type == Types.VARCHAR) {
st.setString(startIndex, str);
} else if (type == Types.CLOB) {
st.setString(startIndex, str);
// throw new UnsupportedOperationException();
} else {
throw new IllegalStateException("Unsupported type " + type);
}
String str = Wkt.newWktEncoder(Wkt.Dialect.POSTGIS_EWKT_1).encode(value);
st.setString(startIndex, str);
}
}

View File

@ -667,7 +667,9 @@ public final class Connections {
// shapes
dropTable(templates, "SHAPES");
stmt.execute("create table \"SHAPES\" (\"ID\" int not null primary key, \"GEOMETRY\" geography(POINT,4326))");
// stmt.execute("create table \"SHAPES\" (\"ID\" int not null primary key, \"GEOMETRY\" geography(POINT,4326))");
stmt.execute("create table \"SHAPES\" (\"ID\" int not null primary key)");
stmt.execute("select AddGeometryColumn('SHAPES', 'GEOMETRY', -1, 'POINT', 2)");
stmt.execute("insert into \"SHAPES\" values (1, 'Point(2 2)')");
stmt.execute("insert into \"SHAPES\" values (2, 'Point(8 7)')");
stmt.execute("insert into \"SHAPES\" values (3, 'Point(1 9)')");

View File

@ -16,7 +16,7 @@ import org.junit.Test;
import com.google.common.collect.Lists;
import com.mysema.query.spatial.PointExpression;
import com.mysema.query.spatial.path.PointPath;
import com.mysema.query.sql.TeradataTemplates;
import com.mysema.query.sql.PostgresTemplates;
import com.mysema.query.sql.spatial.QShapes;
import com.mysema.query.sql.spatial.Shapes;
import com.mysema.query.types.ConstantImpl;
@ -27,9 +27,10 @@ public class SpatialBase extends AbstractBaseTest {
// TEMPORARY
@BeforeClass
public static void setUp() throws Exception {
Connections.initTeradata();
Connections.setTemplates(TeradataTemplates.builder().newLineToSingleSpace().build());
// Connections.setTemplates(PostgresTemplates.builder().quote().newLineToSingleSpace().build());
// Connections.initTeradata();
// Connections.setTemplates(TeradataTemplates.builder().newLineToSingleSpace().build());
Connections.initPostgres();
Connections.setTemplates(PostgresTemplates.builder().quote().newLineToSingleSpace().build());
}
// TEMPORARY

View File

@ -21,7 +21,7 @@ public class QShapes extends com.mysema.query.sql.RelationalPathBase<Shapes> {
private static final long serialVersionUID = 563213127;
public static final QShapes shapes = new QShapes("shapes");
public static final QShapes shapes = new QShapes("SHAPES");
public final GeometryPath<Geometry> geometry = add(new GeometryPath<Geometry>(Geometry.class,
PathMetadataFactory.forProperty(this, "geometry")));
@ -31,7 +31,7 @@ public class QShapes extends com.mysema.query.sql.RelationalPathBase<Shapes> {
public final com.mysema.query.sql.PrimaryKey<Shapes> shapesPkey = createPrimaryKey(id);
public QShapes(String variable) {
super(Shapes.class, forVariable(variable), "public", "shapes");
super(Shapes.class, forVariable(variable), "PUBLIC", "SHAPES");
addMetadata();
}
@ -41,18 +41,18 @@ public class QShapes extends com.mysema.query.sql.RelationalPathBase<Shapes> {
}
public QShapes(Path<? extends Shapes> path) {
super(path.getType(), path.getMetadata(), "public", "shapes");
super(path.getType(), path.getMetadata(), "PUBLIC", "SHAPES");
addMetadata();
}
public QShapes(PathMetadata<?> metadata) {
super(Shapes.class, metadata, "public", "shapes");
super(Shapes.class, metadata, "PUBLIC", "SHAPES");
addMetadata();
}
public void addMetadata() {
addMetadata(geometry, ColumnMetadata.named("geometry").ofType(1111).withSize(2147483647));
addMetadata(id, ColumnMetadata.named("id").ofType(4).withSize(10).notNull());
addMetadata(geometry, ColumnMetadata.named("GEOMETRY").ofType(1111).withSize(2147483647));
addMetadata(id, ColumnMetadata.named("ID").ofType(4).withSize(10).notNull());
}
}

View File

@ -28,7 +28,7 @@ public class SpatialTest {
@Test
public void test() throws SQLException {
Statement stmt = Connections.getStatement();
ResultSet rs = stmt.executeQuery("select geometry from SHAPES");
ResultSet rs = stmt.executeQuery("select \"GEOMETRY\" from \"SHAPES\"");
try {
while (rs.next()) {
System.err.println(rs.getObject(1).getClass().getName());