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_ASTEXT( FunctionKey.apply( "st_astext", "astext" ), StandardBasicTypes.STRING ),
ST_GEOMETRYTYPE( FunctionKey.apply( "st_geometrytype", "geometrytype" ), 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 FunctionKey key;
private final BasicType<?> ReturnType; private final BasicType<?> ReturnType;
private final boolean spatialReturnType;
CommonSpatialFunction(FunctionKey key, BasicType<?> returnType) { CommonSpatialFunction(FunctionKey key, BasicType<?> returnType) {
this.key = key; this.key = key;
ReturnType = returnType; ReturnType = returnType;
spatialReturnType = false;
} }
CommonSpatialFunction(FunctionKey key) {
this.key = key;
ReturnType = null;
spatialReturnType = true;
}
public FunctionKey getKey() { public FunctionKey getKey() {
return key; return key;
} }
@ -34,4 +47,8 @@ public enum CommonSpatialFunction {
public BasicType<?> getReturnType() { public BasicType<?> getReturnType() {
return ReturnType; return ReturnType;
} }
public boolean returnsGeometry() {
return spatialReturnType;
}
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -51,7 +51,7 @@ public class PostgisSupport implements SpatialDialect, Serializable {
} }
public boolean isSpatial(int typeCode){ 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(); public static final SqlServer2008GeometryTypeDescriptor INSTANCE = new SqlServer2008GeometryTypeDescriptor();
@Override @Override
public int getJdbcType() { public int getJdbcTypeCode() {
return Types.ARRAY; 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.GeometryEquality;
import org.hibernate.spatial.testing.datareader.TestDataElement; import org.hibernate.spatial.testing.datareader.TestDataElement;
import org.hibernate.spatial.testing.domain.GeomEntity; import org.hibernate.spatial.testing.domain.GeomEntity;
import org.hibernate.spatial.testing.domain.GeomEntityLike;
import org.hibernate.spatial.testing.domain.SpatialDomainModel; import org.hibernate.spatial.testing.domain.SpatialDomainModel;
import org.hibernate.testing.orm.junit.DomainModel; 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.ArrayList;
import java.util.List; 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.JTSGeometryEquality;
import org.hibernate.spatial.testing.NativeSqlTemplates; import org.hibernate.spatial.testing.NativeSQLTemplates;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import org.hibernate.spatial.testing.TestSupportFactories; import org.hibernate.spatial.testing.TestSupportFactories;
import org.hibernate.spatial.testing.datareader.TestData; import org.hibernate.spatial.testing.datareader.TestData;
import org.hibernate.spatial.testing.datareader.TestDataElement; import org.hibernate.spatial.testing.datareader.TestDataElement;
import org.hibernate.spatial.testing.datareader.TestSupport; import org.hibernate.spatial.testing.datareader.TestSupport;
import org.hibernate.spatial.testing.domain.GeomEntityLike;
import org.hibernate.testing.orm.junit.DialectContext; import org.hibernate.testing.orm.junit.DialectContext;
@Deprecated
public class SpatialTestDataProvider { public class SpatialTestDataProvider {
protected final static String JTS = "jts"; protected final static String JTS = "jts";
protected final NativeSQLTemplates templates;
protected TestData testData; protected TestData testData;
protected GeomCodec codec;
protected JTSGeometryEquality geometryEquality; protected JTSGeometryEquality geometryEquality;
protected NativeSqlTemplates templates;
public SpatialTestDataProvider() { public SpatialTestDataProvider() {
try { try {
TestSupport support = TestSupportFactories.instance().getTestSupportFactory( DialectContext.getDialect() ); TestSupport support = TestSupportFactories.instance().getTestSupportFactory( DialectContext.getDialect() );
templates = support.getNativeSqlTemplates(); templates = support.templates();
codec = support.codec();
testData = support.createTestData( TestSupport.TestDataPurpose.StoreRetrieveData ); testData = support.createTestData( TestSupport.TestDataPurpose.StoreRetrieveData );
geometryEquality = support.createGeometryEquality(); 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() ) { if ( requiresFunctions.isPresent() ) {
String functionKey = requiresFunctions.get().key(); String functionKey = requiresFunctions.get().key();
SpatialFunctionContributor contributor = new SpatialFunctionContributor(); SpatialFunctionContributor contributor = new SpatialFunctionContributor();
contributor.contributeTypes( contributor.contributeFunctions(
functionRegistry::register, functionRegistry,
existing.getSessionFactory().getServiceRegistry() existing.getSessionFactory().getServiceRegistry()
); );
if ( functionRegistry.findFunctionDescriptor( functionKey ) == null ) { 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; package org.hibernate.spatial.testing.datareader;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.config.spi.ConfigurationService; 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.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.DataSourceUtils; import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.JTSGeometryEquality; 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.spatial.testing.SQLExpressionTemplate;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import junit.framework.TestCase;
/** /**
* @author Karel Maesen, Geovise BVBA * @author Karel Maesen, Geovise BVBA
@ -36,7 +34,7 @@ public abstract class TestSupport {
//TODO -- make this abstract //TODO -- make this abstract
public NativeSqlTemplates getNativeSqlTemplates() { public NativeSQLTemplates templates() {
return null; return null;
}; };
@ -55,6 +53,10 @@ public abstract class TestSupport {
public abstract TestData createTestData(TestDataPurpose purpose); public abstract TestData createTestData(TestDataPurpose purpose);
public GeomCodec codec() {
throw new NotYetImplementedFor6Exception();
};
public abstract AbstractExpectationsFactory createExpectationsFactory(DataSourceUtils dataSourceUtils); public abstract AbstractExpectationsFactory createExpectationsFactory(DataSourceUtils dataSourceUtils);
public abstract SQLExpressionTemplate getSQLExpressionTemplate(); public abstract SQLExpressionTemplate getSQLExpressionTemplate();

View File

@ -7,9 +7,6 @@
package org.hibernate.spatial.testing.dialects.postgis; 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; package org.hibernate.spatial.testing.dialects.postgis;
import org.hibernate.spatial.integration.TestGeolatteSpatialPredicates; import org.hibernate.spatial.GeomCodec;
import org.hibernate.spatial.integration.TestJTSSpatialPredicates; import org.hibernate.spatial.dialect.postgis.PGGeometryTypeDescriptor;
import org.hibernate.spatial.integration.TestSpatialFunctions;
import org.hibernate.spatial.testing.AbstractExpectationsFactory; import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.DataSourceUtils; 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.SQLExpressionTemplate;
import org.hibernate.spatial.testing.datareader.TestData; import org.hibernate.spatial.testing.datareader.TestData;
import org.hibernate.spatial.testing.datareader.TestSupport; 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 * @author Karel Maesen, Geovise BVBA
@ -26,9 +26,10 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
*/ */
public class PostgisTestSupport extends TestSupport { public class PostgisTestSupport extends TestSupport {
@Override @Override
public NativeSqlTemplates getNativeSqlTemplates() { public NativeSQLTemplates templates() {
return new PostgisNativeSqlTemplates(); return new PostgisNativeSQLTemplates();
} }
@Override @Override
@ -50,5 +51,18 @@ public class PostgisTestSupport extends TestSupport {
return new PostgisExpressionTemplate(); 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 javax.persistence.Table;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.spatial.integration.GeomEntityLike;
import org.hibernate.spatial.testing.datareader.TestDataElement; import org.hibernate.spatial.testing.datareader.TestDataElement;
import org.geolatte.geom.Geometry; 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>. * 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. * 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 javax.persistence.Table;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.spatial.integration.GeomEntityLike;
import org.hibernate.spatial.testing.datareader.TestDataElement; import org.hibernate.spatial.testing.datareader.TestDataElement;
import org.geolatte.geom.codec.Wkt; 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>. # See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
# #
# Default unit/integration test config. # Default unit/integration test config.
hibernate.dialect @db.dialect@ hibernate.dialect @db.dialect@
hibernate.connection.driver_class @jdbc.driver@ hibernate.connection.driver_class @jdbc.driver@
hibernate.connection.url @jdbc.url@ 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 #hibernate.jdbc.batch_versioned_data true
## Configs for spatial databases (used during testing on local dev environment). ## Configs for spatial databases (used during testing on local dev environment).
# #
#hibernate.dialect org.hibernate.dialect.PostgreSQLDialect # hibernate.dialect org.hibernate.dialect.PostgreSQLDialect
#hibernate.connection.driver_class org.postgresql.Driver # hibernate.connection.driver_class org.postgresql.Driver
#hibernate.connection.url jdbc:postgresql://localhost:5432/hibernate_orm_test?preparedStatementCacheQueries=0 # hibernate.connection.url jdbc:postgresql://localhost:5432/hibernate_orm_test?preparedStatementCacheQueries=0
#hibernate.connection.username hibernate_orm_test # hibernate.connection.username hibernate_orm_test
#hibernate.connection.password hibernate_orm_test hibernate.connection.password hibernate_orm_test
## ##
## GeoDb (H2 spatial extension) ## GeoDb (H2 spatial extension)
## ##