HHH-14738 Using DynamicTests to test function/entity combinations

This commit is contained in:
Karel Maesen 2021-07-29 19:36:37 +02:00
parent 9251e8bfdc
commit 35f42528fb
38 changed files with 580 additions and 274 deletions

View File

@ -17,16 +17,29 @@ public enum CommonSpatialFunction {
ST_ASTEXT( FunctionKey.apply( "st_astext", "astext" ), StandardBasicTypes.STRING ),
ST_GEOMETRYTYPE( FunctionKey.apply( "st_geometrytype", "geometrytype" ), StandardBasicTypes.STRING ),
ST_DIMENSION( FunctionKey.apply( "st_dimension", "dimension" ), StandardBasicTypes.INTEGER );
ST_DIMENSION( FunctionKey.apply( "st_dimension", "dimension" ), StandardBasicTypes.INTEGER ),
ST_SRID( FunctionKey.apply("st_srid", "srid"), StandardBasicTypes.INTEGER),
ST_ENVELOPE( FunctionKey.apply("st_envelope", "envelope"))
;
private final FunctionKey key;
private final BasicType<?> ReturnType;
private final boolean spatialReturnType;
CommonSpatialFunction(FunctionKey key, BasicType<?> returnType) {
this.key = key;
ReturnType = returnType;
spatialReturnType = false;
}
CommonSpatialFunction(FunctionKey key) {
this.key = key;
ReturnType = null;
spatialReturnType = true;
}
public FunctionKey getKey() {
return key;
}
@ -34,4 +47,8 @@ public enum CommonSpatialFunction {
public BasicType<?> getReturnType() {
return ReturnType;
}
public boolean returnsGeometry() {
return spatialReturnType;
}
}

View File

@ -7,8 +7,8 @@
package org.hibernate.spatial.contributor;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
import org.hibernate.service.ServiceRegistry;
/**
@ -18,7 +18,7 @@ public interface ContributorImplementor {
void contributeTypes(TypeContributions typeContributions);
void contributeFunctions(FunctionContributions functionContributions);
void contributeFunctions(SqmFunctionRegistry functionRegistry);
ServiceRegistry getServiceRegistry();
}

View File

@ -7,20 +7,25 @@
package org.hibernate.spatial.contributor;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.FunctionContributor;
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
import org.hibernate.service.ServiceRegistry;
public class SpatialFunctionContributor implements FunctionContributor {
@Override
public void contributeTypes(
FunctionContributions functionContributions, ServiceRegistry serviceRegistry) {
public void contributeFunctions(
SqmFunctionRegistry functionRegistry, ServiceRegistry serviceRegistry) {
ContributorImplementor contributorImplementor = ContributorResolver.resolveSpatialtypeContributorImplementor(
serviceRegistry );
if ( contributorImplementor != null ) {
contributorImplementor.contributeFunctions( functionContributions );
contributorImplementor.contributeFunctions( functionRegistry );
}
}
@Override
public int ordinal() {
return 200;
}
}

View File

@ -40,7 +40,7 @@ public class DB2GeometryTypeDescriptor implements JdbcTypeDescriptor {
}
@Override
public int getJdbcType() {
public int getJdbcTypeCode() {
return Types.CLOB;
}

View File

@ -36,7 +36,7 @@ public class GeoDBGeometryTypeDescriptor implements JdbcTypeDescriptor {
public static final GeoDBGeometryTypeDescriptor INSTANCE = new GeoDBGeometryTypeDescriptor();
@Override
public int getJdbcType() {
public int getJdbcTypeCode() {
return Types.ARRAY;
}

View File

@ -34,7 +34,7 @@ public class HANAGeometryTypeDescriptor implements JdbcTypeDescriptor {
}
@Override
public int getJdbcType() {
public int getJdbcTypeCode() {
return Types.OTHER;
}

View File

@ -31,7 +31,7 @@ public class HANAPointTypeDescriptor implements JdbcTypeDescriptor {
private static final long serialVersionUID = -6978798264716544804L;
@Override
public int getJdbcType() {
public int getJdbcTypeCode() {
return Types.STRUCT;
}

View File

@ -35,7 +35,7 @@ public class MariaDBGeometryTypeDescriptor implements JdbcTypeDescriptor {
final WkbDecoder decoder = Wkb.newDecoder( Wkb.Dialect.MYSQL_WKB );
@Override
public int getJdbcType() {
public int getJdbcTypeCode() {
return Types.ARRAY;
}

View File

@ -41,7 +41,7 @@ public class MySQLGeometryTypeDescriptor implements JdbcTypeDescriptor {
public static final MySQLGeometryTypeDescriptor INSTANCE = new MySQLGeometryTypeDescriptor();
@Override
public int getJdbcType() {
public int getJdbcTypeCode() {
return Types.ARRAY;
}

View File

@ -35,7 +35,7 @@ public class SDOGeometryTypeDescriptor implements JdbcTypeDescriptor {
}
@Override
public int getJdbcType() {
public int getJdbcTypeCode() {
return Types.STRUCT;
}

View File

@ -8,7 +8,6 @@ package org.hibernate.spatial.dialect.oracle;
import java.util.List;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.QueryException;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.spi.Mapping;
@ -88,7 +87,7 @@ class SDOObjectProperty implements SqmFunctionDescriptor {
@Override
public <T> SelfRenderingSqmFunction<T> generateSqmExpression(
List<SqmTypedNode<?>> arguments,
List<? extends SqmTypedNode<?>> arguments,
AllowableFunctionReturnType<T> impliedResultType,
QueryEngine queryEngine,
TypeConfiguration typeConfiguration) {
@ -97,7 +96,7 @@ class SDOObjectProperty implements SqmFunctionDescriptor {
@Override
public <T> SelfRenderingSqmFunction<T> generateAggregateSqmExpression(
List<SqmTypedNode<?>> arguments,
List<? extends SqmTypedNode<?>> arguments,
SqmPredicate filter,
AllowableFunctionReturnType<T> impliedResultType,
QueryEngine queryEngine,

View File

@ -80,7 +80,12 @@ public class PGGeometryTypeDescriptor implements JdbcTypeDescriptor {
@Override
public int getJdbcType() {
public int getJdbcTypeCode() {
return Types.OTHER;
}
@Override
public int getDefaultSqlTypeCode(){
return 5432;
}

View File

@ -7,8 +7,8 @@
package org.hibernate.spatial.dialect.postgis;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
import org.hibernate.spatial.GeolatteGeometryType;
@ -36,13 +36,13 @@ public class PostgisDialectContributor implements ContributorImplementor {
}
@Override
public void contributeFunctions(FunctionContributions functionContributions) {
public void contributeFunctions(SqmFunctionRegistry functionRegistry) {
HSMessageLogger.LOGGER.functionContributions( this.getClass().getCanonicalName() );
PostgisSqmFunctionDescriptors postgisFunctions = new PostgisSqmFunctionDescriptors( getServiceRegistry() );
postgisFunctions.asMap().forEach( (key, desc) -> {
functionContributions.contributeFunction( key.getName(), desc );
key.getAltName().ifPresent( altName -> functionContributions.contributeFunction( altName, desc ) );
functionRegistry.register( key.getName(), desc );
key.getAltName().ifPresent( altName -> functionRegistry.register( altName, desc ) );
} );
}

View File

@ -56,6 +56,14 @@ public class PostgisSqmFunctionDescriptors implements KeyedSqmFunctionDescriptor
)
);
map.put(
ST_ENVELOPE.getKey(), new NamedSqmFunctionDescriptor(
ST_ENVELOPE.getKey().getName(),
true,
StandardArgumentsValidators.exactly( 1 ),
StandardFunctionReturnTypeResolvers.useArgType(1 )
)
);
}
public Map<FunctionKey, SqmFunctionDescriptor> asMap() {

View File

@ -51,7 +51,7 @@ public class PostgisSupport implements SpatialDialect, Serializable {
}
public boolean isSpatial(int typeCode){
return typeCode == Types.OTHER || typeCode == PGGeometryTypeDescriptor.INSTANCE_WKB_1.getJdbcType();
return typeCode == Types.OTHER || typeCode == PGGeometryTypeDescriptor.INSTANCE_WKB_1.getJdbcTypeCode();
}
/**

View File

@ -40,7 +40,7 @@ public class SqlServer2008GeometryTypeDescriptor implements JdbcTypeDescriptor {
public static final SqlServer2008GeometryTypeDescriptor INSTANCE = new SqlServer2008GeometryTypeDescriptor();
@Override
public int getJdbcType() {
public int getJdbcTypeCode() {
return Types.ARRAY;
}

View File

@ -0,0 +1,18 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial;
import org.geolatte.geom.Geometry;
public interface GeomCodec {
Geometry<?> toGeometry(Object in) ;
Object fromGeometry(Geometry<?> in);
}

View File

@ -17,6 +17,7 @@ import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.spatial.testing.GeometryEquality;
import org.hibernate.spatial.testing.datareader.TestDataElement;
import org.hibernate.spatial.testing.domain.GeomEntity;
import org.hibernate.spatial.testing.domain.GeomEntityLike;
import org.hibernate.spatial.testing.domain.SpatialDomainModel;
import org.hibernate.testing.orm.junit.DomainModel;

View File

@ -10,30 +10,30 @@ package org.hibernate.spatial.integration;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.GeomCodec;
import org.hibernate.spatial.testing.JTSGeometryEquality;
import org.hibernate.spatial.testing.NativeSqlTemplates;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import org.hibernate.spatial.testing.NativeSQLTemplates;
import org.hibernate.spatial.testing.TestSupportFactories;
import org.hibernate.spatial.testing.datareader.TestData;
import org.hibernate.spatial.testing.datareader.TestDataElement;
import org.hibernate.spatial.testing.datareader.TestSupport;
import org.hibernate.spatial.testing.domain.GeomEntityLike;
import org.hibernate.testing.orm.junit.DialectContext;
@Deprecated
public class SpatialTestDataProvider {
protected final static String JTS = "jts";
protected final NativeSQLTemplates templates;
protected TestData testData;
protected GeomCodec codec;
protected JTSGeometryEquality geometryEquality;
protected NativeSqlTemplates templates;
public SpatialTestDataProvider() {
try {
TestSupport support = TestSupportFactories.instance().getTestSupportFactory( DialectContext.getDialect() );
templates = support.getNativeSqlTemplates();
templates = support.templates();
codec = support.codec();
testData = support.createTestData( TestSupport.TestDataPurpose.StoreRetrieveData );
geometryEquality = support.createGeometryEquality();
}

View File

@ -1,43 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.integration.functions;
import java.util.function.Function;
import org.hibernate.spatial.testing.BaseSpatialFunctionTestCase;
import org.hibernate.spatial.testing.HQLTemplate;
import org.hibernate.spatial.testing.NativeSQLTemplate;
import org.hibernate.spatial.testing.RequiresFunction;
import org.hibernate.spatial.testing.RowObjectMapper;
@RequiresFunction( key="st_astext" )
public class AsTextFunctionTest extends BaseSpatialFunctionTestCase {
@Override
protected HQLTemplate jqlQueryTemplate() {
return HQLTemplate.from("select g.id, st_astext(g.geom) from %s g");
}
@Override
protected NativeSQLTemplate sqlTemplate() {
return templates.createNativeAsTextTemplate();
}
@Override
protected Function<Object, Object> mapper() {
RowObjectMapper<String> rowObject = new RowObjectMapper<>() {};
return rowObject.mapper();
}
}

View File

@ -0,0 +1,106 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.integration.functions;
import java.util.List;
import java.util.Locale;
import java.util.stream.Stream;
import org.hibernate.spatial.integration.SpatialTestDataProvider;
import org.hibernate.spatial.testing.domain.GeomEntity;
import org.hibernate.spatial.testing.domain.JtsGeomEntity;
import org.hibernate.spatial.testing.domain.SpatialDomainModel;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SessionFactoryScopeAware;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.function.Executable;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SuppressWarnings("ALL")
@DomainModel(modelDescriptorClasses = SpatialDomainModel.class)
@SessionFactory
public class CommonFunctionTests extends SpatialTestDataProvider
implements SessionFactoryScopeAware {
private SessionFactoryScope scope;
List received;
List expected;
@Override
public void injectSessionFactoryScope(SessionFactoryScope scope) {
this.scope = scope;
}
@BeforeEach
public void beforeEach() {
scope.inTransaction( session -> super.entities( JtsGeomEntity.class ).forEach( session::save ) );
scope.inTransaction( session -> super.entities( GeomEntity.class ).forEach( session::save ) );
}
@AfterEach
public void cleanup() {
scope.inTransaction( session -> session.createQuery( "delete from GeomEntity" ).executeUpdate() );
scope.inTransaction( session -> session.createQuery( "delete from JtsGeomEntity" ).executeUpdate() );
}
@TestFactory
public Stream<DynamicTest> testFunction() {
return
TestTemplates.all( templates)
// TODO -- filter for supported functions
.flatMap( t -> Stream.of(
t.build( Model.JTSMODEL, codec ),
t.build( Model.GLMODEL, codec )
) )
.flatMap( this::buildTests );
}
protected Stream<DynamicTest> buildTests(FunctionTestTemplate template) {
return Stream.of(
template.getFunctionName(),
template.getAltFunctionName()
)
.filter( s -> s != null )
.map( fn -> DynamicTest.dynamicTest(
displayName( template, fn ), executableTest( template, fn )
) );
}
protected <T> String displayName(FunctionTestTemplate template, String fnName) {
return String.format(
Locale.ROOT,
"Test for function %s on entity %s",
fnName,
template.getModel().entityClass.getSimpleName()
);
}
protected <T> Executable executableTest(FunctionTestTemplate template, String fnName) {
Executable testF = () -> {
expected = template.executeNativeQuery( scope );
received = template.executeHQL( scope, fnName);
assertEquals( expected, received );
};
return testF;
}
}

View File

@ -0,0 +1,158 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.integration.functions;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.hibernate.Session;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.query.NativeQuery;
import org.hibernate.spatial.CommonSpatialFunction;
import org.hibernate.spatial.GeomCodec;
import org.hibernate.spatial.testing.HQLTemplate;
import org.hibernate.spatial.testing.NativeSQLTemplate;
import org.hibernate.type.Type;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
@SuppressWarnings({ "rawtypes", "unchecked" })
public class FunctionTestTemplate {
final private CommonSpatialFunction spatialFunction;
final private HQLTemplate hqlTemplate;
final private NativeSQLTemplate sqlTemplate;
final private RowObjectMapper rowObjectMapper;
final private Model model;
final private List<Param> parameters;
final private GeomCodec codec;
FunctionTestTemplate(
CommonSpatialFunction function,
HQLTemplate hqlTemplate,
NativeSQLTemplate sqlTemplate,
RowObjectMapper rowObjectMapper,
Model model,
List<Param> params,
GeomCodec codec) {
this.spatialFunction = function;
this.hqlTemplate = hqlTemplate;
this.sqlTemplate = sqlTemplate;
this.rowObjectMapper = rowObjectMapper;
this.model = model;
this.parameters = params;
this.codec = codec;
}
public String getFunctionName() {
return this.spatialFunction.getKey().getName();
}
public String getAltFunctionName() {
return this.spatialFunction.getKey().getAltName().orElse( null );
}
public Model getModel() {
return model;
}
public List<Object> executeNativeQuery(SessionFactoryScope scope) {
PersistentClass binding = scope.getMetadataImplementor()
.getEntityBinding( model.entityClass.getCanonicalName() );
String table = binding.getTable().getName();
final AtomicReference<List<Object>> results = new AtomicReference<>();
scope.inSession( session -> results.set( createNativeQuery( session, table ).getResultList() ) );
return map( results.get() );
}
private NativeQuery<Object> createNativeQuery(Session session, String table) {
return session.createNativeQuery( sqlTemplate.mkNativeSQLString( table ) );
}
private List<Object> map(List<Object> list) {
Stream<Object> stream = list
.stream().map( this::mapRow );
return stream.collect( Collectors.toList() );
}
private Object mapRow(Object object) {
Data data = rowObjectMapper.apply( object );
if ( this.spatialFunction.returnsGeometry() ) {
data.datum = this.model.from.apply( codec.toGeometry( data.datum ) );
return data;
}
return data;
}
public List executeHQL(SessionFactoryScope scope, String functionName) {
final AtomicReference<List> results = new AtomicReference<>();
final String entity = model.entityClass.getCanonicalName();
scope.inSession(
session -> results.set( session.createQuery(
hqlTemplate.mkHQLString( functionName, entity ) ).getResultList() ) );
return (List) results.get().stream().map( rowObjectMapper::apply ).collect( Collectors.toList() );
}
static class Param {
final Object value;
final Type type;
public Param(Object value, Type type) {
this.value = value;
this.type = type;
}
}
static class Builder {
CommonSpatialFunction key;
HQLTemplate hql = new HQLTemplate( "select id, %s(geom) from %s" );
NativeSQLTemplate sql;
RowObjectMapper mapper;
List<Param> params = new ArrayList<>();
FunctionTestTemplate build(Model model, GeomCodec codec) {
if ( this.mapper == null ) {
this.mapper = new RowObjectMapper() {
};
}
return new FunctionTestTemplate( key, hql, sql, mapper, model, params, codec );
}
Builder key(CommonSpatialFunction key) {
this.key = key;
return this;
}
Builder hql(String hqlString) {
this.hql = new HQLTemplate( hqlString );
return this;
}
Builder sql(String sqlString) {
this.sql = new NativeSQLTemplate( sqlString );
return this;
}
Builder parameter(Object value, Type type) {
this.params.add( new Param( value, type ) );
return this;
}
}
}

View File

@ -1,38 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.integration.functions;
import java.util.function.Function;
import org.hibernate.spatial.testing.BaseSpatialFunctionTestCase;
import org.hibernate.spatial.testing.HQLTemplate;
import org.hibernate.spatial.testing.NativeSQLTemplate;
import org.hibernate.spatial.testing.RequiresFunction;
import org.hibernate.spatial.testing.RowObjectMapper;
@RequiresFunction(key = "st_dimension")
public class GetDimensionTest extends BaseSpatialFunctionTestCase {
@Override
protected HQLTemplate jqlQueryTemplate() {
return HQLTemplate.from( "select g.id, st_dimension(g.geom) from %s g" );
}
@Override
protected NativeSQLTemplate sqlTemplate() {
return templates.createNativeDimensionTemplate();
}
@Override
protected Function<Object, Object> mapper() {
RowObjectMapper<Integer> rowObject = new RowObjectMapper<>() {
};
return rowObject.mapper();
}
}

View File

@ -1,50 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.integration.functions;/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
import java.util.function.Function;
import org.hibernate.spatial.testing.BaseSpatialFunctionTestCase;
import org.hibernate.spatial.testing.HQLTemplate;
import org.hibernate.spatial.testing.NativeSQLTemplate;
import org.hibernate.spatial.testing.RequiresFunction;
import org.hibernate.spatial.testing.RowObjectMapper;
@RequiresFunction(key = "st_geometrytype")
public class GetGeometryTypeTest extends BaseSpatialFunctionTestCase {
@Override
protected HQLTemplate jqlQueryTemplate() {
return HQLTemplate.from( "select g.id, st_geometrytype(g.geom) from %s g" );
}
@Override
protected NativeSQLTemplate sqlTemplate() {
return templates.createNativeGeometryTypeTemplate();
}
@Override
protected Function<Object, Object> mapper() {
RowObjectMapper<String> rowObject = new RowObjectMapper<>() {
};
return rowObject.mapper();
}
}

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.integration.functions;
import java.util.function.Function;
import org.hibernate.spatial.testing.domain.GeomEntity;
import org.hibernate.spatial.testing.domain.JtsGeomEntity;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.jts.JTS;
@SuppressWarnings({ "unchecked", "rawtypes" })
enum Model {
JTSMODEL(
JtsGeomEntity.class,
obj -> JTS.from( (org.locationtech.jts.geom.Geometry) obj ),
geom -> (Object) JTS.to( geom )
),
GLMODEL(
GeomEntity.class,
obj -> (Geometry) obj,
geom -> geom
);
final Class<?> entityClass;
final Function<Object, Geometry> to;
final Function<Geometry, Object> from;
Model(
Class<?> entityClass,
Function<Object, Geometry> to,
Function<Geometry, Object> from
) {
this.entityClass = entityClass;
this.to = to;
this.from = from;
}
}

View File

@ -0,0 +1,62 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.integration.functions;
import java.util.Objects;
import java.util.function.Function;
public interface RowObjectMapper<T> {
default Data apply(Object obj) {
Object[] row = (Object[]) obj;
return new Data( (Integer) row[0], (T) row[1] );
}
}
class Data {
final Integer id;
Object datum;
Data(Integer id, Object datum) {
this.id = id;
this.datum = datum;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Data data = (Data) o;
return Objects.equals( id, data.id ) && Objects.equals( datum, data.datum );
}
@Override
public int hashCode() {
return Objects.hash( id, datum );
}
@Override
public String toString() {
return "Data{" +
"id=" + id +
", datum=" + datum +
'}';
}
}

View File

@ -0,0 +1,41 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.integration.functions;
import java.util.Map;
import java.util.stream.Stream;
import org.hibernate.spatial.CommonSpatialFunction;
import org.hibernate.spatial.FunctionKey;
import org.hibernate.spatial.testing.NativeSQLTemplates;
public abstract class TestTemplates {
static FunctionTestTemplate.Builder builder() {
return new FunctionTestTemplate.Builder();
}
public static Stream<FunctionTestTemplate.Builder> all(NativeSQLTemplates sqlTemplates) {
Map<CommonSpatialFunction, String> templates = sqlTemplates.all();
return templates
.keySet()
.stream()
.map( key -> builder()
.key( key )
.sql( templates.get( key ) ) );
}
}

View File

@ -0,0 +1,34 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.testing;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.spatial.CommonSpatialFunction;
import static org.hibernate.spatial.CommonSpatialFunction.*;
public class NativeSQLTemplates {
private final Map<CommonSpatialFunction, String> sqls = new HashMap<>();
// Note that we alias the function invocation so that
// we can map the return value to the required type
public NativeSQLTemplates() {
sqls.put( ST_ASTEXT, "select id, st_astext(geom) as result from %s" );
sqls.put( ST_GEOMETRYTYPE, "select id, st_geometrytype(geom) as result from %s" );
sqls.put( ST_DIMENSION, "select id, st_dimension(geom) as result from %s" );
sqls.put( ST_ENVELOPE, "select id, st_envelope(geom) as result from %s" );
}
public Map<CommonSpatialFunction, String> all() {
return Collections.unmodifiableMap( this.sqls );
}
}

View File

@ -1,25 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.testing;
public class NativeSqlTemplates {
public NativeSQLTemplate createNativeAsTextTemplate() {
return new NativeSQLTemplate( "select id, st_astext(geom) from %s" );
}
public NativeSQLTemplate createNativeGeometryTypeTemplate() {
return new NativeSQLTemplate( "select id, st_geometrytype(geom) from %s" );
}
public NativeSQLTemplate createNativeDimensionTemplate() {
return new NativeSQLTemplate( "select id, st_dimension(geom) from %s" );
}
}

View File

@ -60,8 +60,8 @@ public class RequireFunctionExtension implements ExecutionCondition {
if ( requiresFunctions.isPresent() ) {
String functionKey = requiresFunctions.get().key();
SpatialFunctionContributor contributor = new SpatialFunctionContributor();
contributor.contributeTypes(
functionRegistry::register,
contributor.contributeFunctions(
functionRegistry,
existing.getSessionFactory().getServiceRegistry()
);
if ( functionRegistry.findFunctionDescriptor( functionKey ) == null ) {

View File

@ -1,58 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.testing;
import java.util.Objects;
import java.util.function.Function;
public interface RowObjectMapper<T> {
default Function<Object, Object> mapper() {
return obj -> {
Object[] row = (Object[]) obj;
return new Data<>( (Integer) row[0], (T) row[1] );
};
}
static class Data<T> {
final private Integer id;
final private T datum;
Data(Integer id, T datum) {
this.id = id;
this.datum = datum;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Data data = (Data) o;
return Objects.equals( id, data.id ) && Objects.equals( datum, data.datum );
}
@Override
public int hashCode() {
return Objects.hash( id, datum );
}
@Override
public String toString() {
return "Data{" +
"id=" + id +
", datum=" + datum +
'}';
}
}
}

View File

@ -14,18 +14,16 @@
package org.hibernate.spatial.testing.datareader;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeomCodec;
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.JTSGeometryEquality;
import org.hibernate.spatial.testing.NativeSqlTemplates;
import org.hibernate.spatial.testing.NativeSQLTemplates;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import junit.framework.TestCase;
/**
* @author Karel Maesen, Geovise BVBA
@ -36,7 +34,7 @@ public abstract class TestSupport {
//TODO -- make this abstract
public NativeSqlTemplates getNativeSqlTemplates() {
public NativeSQLTemplates templates() {
return null;
};
@ -55,6 +53,10 @@ public abstract class TestSupport {
public abstract TestData createTestData(TestDataPurpose purpose);
public GeomCodec codec() {
throw new NotYetImplementedFor6Exception();
};
public abstract AbstractExpectationsFactory createExpectationsFactory(DataSourceUtils dataSourceUtils);
public abstract SQLExpressionTemplate getSQLExpressionTemplate();

View File

@ -7,9 +7,6 @@
package org.hibernate.spatial.testing.dialects.postgis;
import org.hibernate.spatial.testing.NativeSqlTemplates;
import org.hibernate.spatial.testing.NativeSQLTemplates;
public class PostgisNativeSqlTemplates extends NativeSqlTemplates {
}
public class PostgisNativeSQLTemplates extends NativeSQLTemplates{}

View File

@ -8,17 +8,17 @@
package org.hibernate.spatial.testing.dialects.postgis;
import org.hibernate.spatial.integration.TestGeolatteSpatialPredicates;
import org.hibernate.spatial.integration.TestJTSSpatialPredicates;
import org.hibernate.spatial.integration.TestSpatialFunctions;
import org.hibernate.spatial.GeomCodec;
import org.hibernate.spatial.dialect.postgis.PGGeometryTypeDescriptor;
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.NativeSqlTemplates;
import org.hibernate.spatial.testing.NativeSQLTemplates;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import org.hibernate.spatial.testing.datareader.TestData;
import org.hibernate.spatial.testing.datareader.TestSupport;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkt;
/**
* @author Karel Maesen, Geovise BVBA
@ -26,9 +26,10 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
*/
public class PostgisTestSupport extends TestSupport {
@Override
public NativeSqlTemplates getNativeSqlTemplates() {
return new PostgisNativeSqlTemplates();
public NativeSQLTemplates templates() {
return new PostgisNativeSQLTemplates();
}
@Override
@ -50,5 +51,18 @@ public class PostgisTestSupport extends TestSupport {
return new PostgisExpressionTemplate();
}
public GeomCodec codec() {
return new GeomCodec() {
@Override
public Geometry<?> toGeometry(Object in) {
return PGGeometryTypeDescriptor.INSTANCE_WKB_1.toGeometry( in );
}
@Override
public Object fromGeometry(Geometry<?> in) {
return Wkt.toWkt( in, Wkt.Dialect.POSTGIS_EWKT_1 );
}
};
}
}

View File

@ -19,7 +19,6 @@ import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.dialect.Dialect;
import org.hibernate.spatial.integration.GeomEntityLike;
import org.hibernate.spatial.testing.datareader.TestDataElement;
import org.geolatte.geom.Geometry;

View File

@ -5,7 +5,14 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.integration;
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.testing.domain;
/**
* Created by Karel Maesen, Geovise BVBA on 15/02/2018.

View File

@ -19,7 +19,6 @@ import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.dialect.Dialect;
import org.hibernate.spatial.integration.GeomEntityLike;
import org.hibernate.spatial.testing.datareader.TestDataElement;
import org.geolatte.geom.codec.Wkt;

View File

@ -6,6 +6,7 @@
# See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
#
# Default unit/integration test config.
hibernate.dialect @db.dialect@
hibernate.connection.driver_class @jdbc.driver@
hibernate.connection.url @jdbc.url@
@ -26,11 +27,11 @@ hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFa
#hibernate.jdbc.batch_versioned_data true
## Configs for spatial databases (used during testing on local dev environment).
#
#hibernate.dialect org.hibernate.dialect.PostgreSQLDialect
#hibernate.connection.driver_class org.postgresql.Driver
#hibernate.connection.url jdbc:postgresql://localhost:5432/hibernate_orm_test?preparedStatementCacheQueries=0
#hibernate.connection.username hibernate_orm_test
#hibernate.connection.password hibernate_orm_test
# hibernate.dialect org.hibernate.dialect.PostgreSQLDialect
# hibernate.connection.driver_class org.postgresql.Driver
# hibernate.connection.url jdbc:postgresql://localhost:5432/hibernate_orm_test?preparedStatementCacheQueries=0
# hibernate.connection.username hibernate_orm_test
hibernate.connection.password hibernate_orm_test
##
## GeoDb (H2 spatial extension)
##