HHH-12798: Fix for nested spatial functions on SAP HANA

This commit is contained in:
Jonathan Bregler 2018-07-12 12:32:16 +02:00 committed by Vlad Mihalcea
parent a9d5847fa9
commit dfe0bcbbca
3 changed files with 115 additions and 53 deletions

View File

@ -57,50 +57,44 @@ public class HANASpatialFunction extends StandardSQLFunction {
if ( arguments.size() == 0 ) {
return getName() + "()";
}
else {
final StringBuilder buf = new StringBuilder();
int firstArgumentIndex;
if ( staticFunction ) {
// Add function call
buf.append( getName() );
firstArgumentIndex = 0;
}
else {
// If the first argument is an expression, e.g. a nested function, strip the .ST_AsEWKB() suffix
buf.append( stripEWKBSuffix( arguments.get( 0 ) ) );
// Add function call
buf.append( "." ).append( getName() );
firstArgumentIndex = 1;
}
buf.append( '(' );
// Add function arguments
for ( int i = firstArgumentIndex; i < arguments.size(); i++ ) {
final Object argument = arguments.get( i );
// Check if first argument needs to be parsed from EWKB. This is the case if the first argument is a
// parameter that is set as EWKB or if it's a nested function call.
final boolean parseFromWKB = ( isGeometryArgument( i ) && "?".equals( argument ) );
if ( parseFromWKB ) {
buf.append( "ST_GeomFromEWKB(" );
}
buf.append( stripEWKBSuffix( argument ) );
if ( parseFromWKB ) {
buf.append( ")" );
}
if ( i < arguments.size() - 1 ) {
buf.append( ", " );
}
}
buf.append( ')' );
// If it doesn't specify an explicit type, assume it's a geometry
if ( this.getType() == null ) {
buf.append( AS_EWKB_SUFFIX );
}
return buf.toString();
final StringBuilder buf = new StringBuilder();
int firstArgumentIndex;
if ( this.staticFunction ) {
// Add function call
buf.append( getName() );
firstArgumentIndex = 0;
}
else {
// If the first argument is an expression, e.g. a nested function, strip the .ST_AsEWKB() suffix
Object argument = arguments.get( 0 );
final boolean parseFromWKB = ( "?".equals( argument ) );
appendArgument( argument, parseFromWKB, buf );
// Add function call
buf.append( "." ).append( getName() );
firstArgumentIndex = 1;
}
buf.append( '(' );
// Add function arguments
for ( int i = firstArgumentIndex; i < arguments.size(); i++ ) {
final Object argument = arguments.get( i );
// Check if first argument needs to be parsed from EWKB. This is the case if the first argument is a
// parameter that is set as EWKB or if it's a nested function call.
final boolean parseFromWKB = ( isGeometryArgument( i ) && "?".equals( argument ) );
appendArgument( argument, parseFromWKB, buf );
if ( i < arguments.size() - 1 ) {
buf.append( ", " );
}
}
buf.append( ')' );
// If it doesn't specify an explicit type, assume it's a geometry
if ( this.getType() == null ) {
buf.append( AS_EWKB_SUFFIX );
}
return buf.toString();
}
private Object stripEWKBSuffix(Object argument) {
@ -115,4 +109,14 @@ public class HANASpatialFunction extends StandardSQLFunction {
private boolean isGeometryArgument(int idx) {
return this.argumentIsGeometryTypeMask.size() > idx && this.argumentIsGeometryTypeMask.get( idx );
}
private void appendArgument(Object argument, boolean parseFromWKB, StringBuilder buf) {
if ( parseFromWKB ) {
buf.append( "ST_GeomFromEWKB(" );
}
buf.append( stripEWKBSuffix( argument ) );
if ( parseFromWKB ) {
buf.append( ")" );
}
}
}

View File

@ -1018,6 +1018,31 @@ public class TestHANASpatialFunctions extends TestSpatialFunctions {
retrieveHQLResultsAndCompare( dbexpected, hql, pckg );
}
@Test
public void test_nestedfunction_on_jts() throws SQLException {
nestedfunction( JTS );
}
@Test
public void test_nestedfunction_on_geolatte() throws SQLException {
nestedfunction( GEOLATTE );
}
public void nestedfunction(String pckg) throws SQLException {
Map<Integer, Geometry> dbexpected = hanaExpectationsFactory.getNestedFunctionInner( expectationsFactory.getTestPolygon() );
String hql = format(
"SELECT id, geom FROM org.hibernate.spatial.integration.%s.GeomEntity g where dwithin(geom, srid(:filter, 0), 1) = true",
pckg );
Map<String, Object> params = createQueryParams( "filter", expectationsFactory.getTestPolygon() );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
dbexpected = hanaExpectationsFactory.getNestedFunctionOuter( expectationsFactory.getTestPolygon() );
hql = format(
"SELECT id, geom FROM org.hibernate.spatial.integration.%s.GeomEntity g where dwithin(:filter, srid(geom, 0), 1) = true",
pckg );
retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg );
}
private String getGeometryTypeFromPackage(String pckg) {
switch ( pckg ) {
case GEOLATTE:

View File

@ -925,7 +925,7 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
"select t.id, t.geom.ST_SnapToGrid() from GeomTest t where t.geom.ST_SRID() = "
+ getTestSrid() );
}
/**
* Returns the expected startpoint of all testsuite-suite geometries.
*
@ -939,7 +939,7 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
private NativeSQLStatement createNativeStartPointStatement() {
return createNativeSQLStatement( "select id, t.geom.ST_StartPoint() from GeomTest t where t.geom.ST_GeometryType() = 'ST_LineString'" );
}
/**
* Returns the expected aggregated union of all testsuite-suite geometries.
*
@ -953,7 +953,7 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
private NativeSQLStatement createNativeUnionAggrStatement() {
return createNativeSQLStatement( "select cast(count(*) as int), ST_UnionAggr(t.geom) from GeomTest t" );
}
/**
* Returns the x coordinate of all testsuite-suite geometries.
*
@ -969,7 +969,7 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
"select t.id, t.geom.ST_X() from GeomTest t where t.geom.ST_GeometryType() in ('ST_Point') and t.geom.ST_SRID() = "
+ getTestSrid() );
}
/**
* Returns the maximum x coordinate of all testsuite-suite geometries.
*
@ -985,7 +985,7 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
"select t.id, t.geom.ST_XMax() from GeomTest t where t.geom.ST_SRID() = "
+ getTestSrid() );
}
/**
* Returns the minimum x coordinate of all testsuite-suite geometries.
*
@ -1001,7 +1001,7 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
"select t.id, t.geom.ST_XMin() from GeomTest t where t.geom.ST_SRID() = "
+ getTestSrid() );
}
/**
* Returns the y coordinate of all testsuite-suite geometries.
*
@ -1017,7 +1017,7 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
"select t.id, t.geom.ST_Y() from GeomTest t where t.geom.ST_GeometryType() in ('ST_Point') and t.geom.ST_SRID() = "
+ getTestSrid() );
}
/**
* Returns the maximum y coordinate of all testsuite-suite geometries.
*
@ -1033,7 +1033,7 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
"select t.id, t.geom.ST_YMax() from GeomTest t where t.geom.ST_SRID() = "
+ getTestSrid() );
}
/**
* Returns the minimum y coordinate of all testsuite-suite geometries.
*
@ -1049,7 +1049,7 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
"select t.id, t.geom.ST_YMin() from GeomTest t where t.geom.ST_SRID() = "
+ getTestSrid() );
}
/**
* Returns the z coordinate of all testsuite-suite geometries.
*
@ -1065,7 +1065,7 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
"select t.id, t.geom.ST_Z() from GeomTest t where t.geom.ST_GeometryType() in ('ST_Point') and t.geom.ST_SRID() = "
+ getTestSrid() );
}
/**
* Returns the maximum z coordinate of all testsuite-suite geometries.
*
@ -1081,7 +1081,7 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
"select t.id, t.geom.ST_ZMax() from GeomTest t where t.geom.ST_SRID() = "
+ getTestSrid() );
}
/**
* Returns the minimum z coordinate of all testsuite-suite geometries.
*
@ -1097,4 +1097,37 @@ public class HANAExpectationsFactory extends AbstractExpectationsFactory {
"select t.id, t.geom.ST_ZMin() from GeomTest t where t.geom.ST_SRID() = "
+ getTestSrid() );
}
/**
* Returns the result of a nested function call with a parameter inside the inner function
*
* @return map of identifier, geometry
* @throws SQLException
*/
public Map<Integer, Geometry> getNestedFunctionInner(Geometry geom) throws SQLException {
return retrieveExpected( createNativeNestedFunctionInnerStatement( geom ), GEOMETRY );
}
private NativeSQLStatement createNativeNestedFunctionInnerStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom from GeomTest t where t.geom.ST_WithinDistance(ST_GeomFromText(?, " + getTestSrid()
+ ").ST_SRID(0), 1) = 1",
geom.toText() );
}
/**
* Returns the result of a nested function call with a parameter inside the outer function
*
* @return map of identifier, geometry
* @throws SQLException
*/
public Map<Integer, Geometry> getNestedFunctionOuter(Geometry geom) throws SQLException {
return retrieveExpected( createNativeNestedFunctionOuterStatement( geom ), GEOMETRY );
}
private NativeSQLStatement createNativeNestedFunctionOuterStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom from GeomTest t where ST_GeomFromText(?, " + getTestSrid() + ").ST_WithinDistance(geom.ST_SRID(0), 1) = 1",
geom.toText() );
}
}