diff --git a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/AbstractWhereBuilder.java b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/AbstractWhereBuilder.java
index a8a9bde54b..1f3e86384a 100644
--- a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/AbstractWhereBuilder.java
+++ b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/AbstractWhereBuilder.java
@@ -77,6 +77,7 @@
import org.deegree.filter.sort.SortProperty;
import org.deegree.filter.spatial.BBOX;
import org.deegree.filter.spatial.SpatialOperator;
+import org.deegree.filter.temporal.TemporalOperator;
import org.deegree.geometry.Geometry;
import org.deegree.sqldialect.SQLDialect;
import org.deegree.sqldialect.filter.expression.SQLArgument;
@@ -313,6 +314,9 @@ protected SQLExpression toProtoSQL( Operator op )
sql = toProtoSQL( (SpatialOperator) op );
break;
}
+ case TEMPORAL: {
+ sql = toProtoSQL( (TemporalOperator) op );
+ }
}
return sql;
}
@@ -487,7 +491,7 @@ protected SQLExpression toProtoSQL( ComparisonOperator op )
return sqlOper;
}
- private void inferType( SQLExpression expr1, SQLExpression expr2 ) {
+ protected void inferType( SQLExpression expr1, SQLExpression expr2 ) {
PrimitiveType pt1 = expr1.getPrimitiveType();
PrimitiveType pt2 = expr2.getPrimitiveType();
if ( pt1 == null && pt2 != null ) {
@@ -501,7 +505,7 @@ private void inferType( SQLExpression expr1, SQLExpression expr2 ) {
}
}
- private void inferType( SQLExpression expr1, SQLExpression expr2, SQLExpression expr3 ) {
+ protected void inferType( SQLExpression expr1, SQLExpression expr2, SQLExpression expr3 ) {
PrimitiveType pt1 = expr1.getPrimitiveType();
PrimitiveType pt2 = expr2.getPrimitiveType();
PrimitiveType pt3 = expr3.getPrimitiveType();
@@ -537,6 +541,10 @@ private PropertyIsLike buildIsLike( Expression propName, Expression literal, boo
matchCase, null );
}
+ protected void addExpression( SQLOperationBuilder builder, SQLExpression expr ) {
+ addExpression( builder, expr, true );
+ }
+
protected void addExpression( SQLOperationBuilder builder, SQLExpression expr, Boolean matchCase ) {
if ( matchCase == null || matchCase ) {
builder.add( expr );
@@ -658,6 +666,23 @@ protected SQLOperation toProtoSQL( LogicalOperator op )
protected abstract SQLOperation toProtoSQL( SpatialOperator op )
throws UnmappableException, FilterEvaluationException;
+ /**
+ * Translates the given {@link TemporalOperator} into an {@link SQLOperation}.
+ *
+ * @param op
+ * temporal operator to be translated, must not be null
+ * @return corresponding SQL expression, may be null
+ * @throws UnmappableException
+ * if translation is not possible (usually due to unmappable property names)
+ * @throws FilterEvaluationException
+ * if the filter contains invalid {@link ValueReference}s
+ */
+ protected SQLOperation toProtoSQL( TemporalOperator op )
+ throws UnmappableException, FilterEvaluationException {
+ LOG.warn( "Mapping of temporal operators to SQL is not implemented (and probably not possible)." );
+ return null;
+ }
+
/**
* Translates the given {@link Expression} into an {@link SQLExpression}.
*
@@ -837,7 +862,8 @@ protected SQLExpression toProtoSQL( Literal> literal )
throw new UnmappableException( "Only primitive valued literals are currently supported." );
}
}
- PrimitiveParticleConverter converter = new DefaultPrimitiveConverter( new PrimitiveType( STRING ), null, false );
+ PrimitiveParticleConverter converter = new DefaultPrimitiveConverter( new PrimitiveType( STRING ), null,
+ false );
return new SQLArgument( null, converter );
}
diff --git a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-postgis/src/main/java/org/deegree/sqldialect/postgis/PostGISWhereBuilder.java b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-postgis/src/main/java/org/deegree/sqldialect/postgis/PostGISWhereBuilder.java
index 7dc08a62b8..dc99b8301d 100644
--- a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-postgis/src/main/java/org/deegree/sqldialect/postgis/PostGISWhereBuilder.java
+++ b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-postgis/src/main/java/org/deegree/sqldialect/postgis/PostGISWhereBuilder.java
@@ -36,12 +36,15 @@
package org.deegree.sqldialect.postgis;
import static java.sql.Types.BOOLEAN;
+import static org.deegree.commons.tom.primitive.BaseType.DATE_TIME;
import static org.deegree.commons.tom.primitive.BaseType.DECIMAL;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
import org.deegree.commons.tom.TypedObjectNode;
+import org.deegree.commons.tom.datetime.ISO8601Converter;
import org.deegree.commons.tom.primitive.PrimitiveType;
import org.deegree.commons.tom.primitive.PrimitiveValue;
import org.deegree.commons.tom.sql.DefaultPrimitiveConverter;
@@ -68,6 +71,7 @@
import org.deegree.filter.spatial.SpatialOperator;
import org.deegree.filter.spatial.Touches;
import org.deegree.filter.spatial.Within;
+import org.deegree.filter.temporal.TemporalOperator;
import org.deegree.geometry.Geometry;
import org.deegree.sqldialect.filter.AbstractWhereBuilder;
import org.deegree.sqldialect.filter.PropertyNameMapper;
@@ -77,6 +81,10 @@
import org.deegree.sqldialect.filter.expression.SQLOperation;
import org.deegree.sqldialect.filter.expression.SQLOperationBuilder;
import org.deegree.sqldialect.filter.islike.IsLikeString;
+import org.deegree.time.position.IndeterminateValue;
+import org.deegree.time.position.TimePosition;
+import org.deegree.time.primitive.GenericTimeInstant;
+import org.deegree.time.primitive.GenericTimePeriod;
/**
* {@link AbstractWhereBuilder} implementation for PostGIS databases.
@@ -113,7 +121,7 @@ public class PostGISWhereBuilder extends AbstractWhereBuilder {
*/
public PostGISWhereBuilder( PostGISDialect dialect, PropertyNameMapper mapper, OperatorFilter filter,
SortProperty[] sortCrit, boolean allowPartialMappings, boolean useLegacyPredicates )
- throws FilterEvaluationException, UnmappableException {
+ throws FilterEvaluationException, UnmappableException {
super( dialect, mapper, filter, sortCrit );
this.useLegacyPredicates = useLegacyPredicates;
build( allowPartialMappings );
@@ -157,8 +165,7 @@ protected String getStringValueFromFunction( Expression pattern )
appendParamsFromFunction( function, params );
TypedObjectNode value = evaluateFunction( function, params );
if ( !( value instanceof PrimitiveValue ) ) {
- throw new UnsupportedOperationException(
- "SQL IsLike request with a function evaluating to a non-primitive value is not supported!" );
+ throw new UnsupportedOperationException( "SQL IsLike request with a function evaluating to a non-primitive value is not supported!" );
}
String valueAsString = ( (PrimitiveValue) value ).getAsText();
return valueAsString;
@@ -385,6 +392,96 @@ protected SQLOperation toProtoSQL( SpatialOperator op )
return builder.toOperation();
}
+ protected SQLOperation toProtoSQL( TemporalOperator op )
+ throws UnmappableException, FilterEvaluationException {
+ SQLOperation sql = null;
+ switch ( op.getSubType() ) {
+ case AFTER: {
+ SQLExpression first = toProtoSQL( op.getParameter1() );
+ Expression parameter2 = op.getParameter2();
+ SQLExpression second;
+ if ( isTimeInstant( parameter2 ) ) {
+ TimePosition timePosition = ( (GenericTimeInstant) ( (Literal>) parameter2 ).getValue() ).getPosition();
+ second = createDateExpression( timePosition );
+ } else if ( isTimePeriod( parameter2 ) ) {
+ TimePosition end = ( (GenericTimePeriod) ( (Literal>) parameter2 ).getValue() ).getEndPosition();
+ second = createDateExpression( end );
+ } else {
+ second = toProtoSQL( parameter2 );
+ }
+ inferType( first, second );
+ sql = createSqlAfter( first, second );
+ break;
+ }
+ case BEFORE: {
+ SQLExpression first = toProtoSQL( op.getParameter1() );
+ Expression parameter2 = op.getParameter2();
+ SQLExpression second;
+ if ( isTimeInstant( parameter2 ) ) {
+ TimePosition timePosition = ( (GenericTimeInstant) ( (Literal>) parameter2 ).getValue() ).getPosition();
+ second = createDateExpression( timePosition );
+ } else if ( isTimePeriod( parameter2 ) ) {
+ TimePosition begin = ( (GenericTimePeriod) ( (Literal>) parameter2 ).getValue() ).getBeginPosition();
+ second = createDateExpression( begin );
+ } else {
+ second = toProtoSQL( parameter2 );
+ }
+ inferType( first, second );
+ sql = createSqlBefore( first, second );
+ break;
+ }
+ case TEQUALS: {
+ SQLExpression first = toProtoSQL( op.getParameter1() );
+ Expression parameter2 = op.getParameter2();
+ SQLExpression second;
+ if ( isTimeInstant( parameter2 ) ) {
+ TimePosition timePosition = ( (GenericTimeInstant) ( (Literal>) parameter2 ).getValue() ).getPosition();
+ second = createDateExpression( timePosition );
+ } else {
+ second = toProtoSQL( parameter2 );
+ }
+ inferType( first, second );
+ sql = createSqlEquals( first, second );
+ break;
+ }
+ case DURING: {
+ Expression parameter2 = op.getParameter2();
+ if ( isTimePeriod( parameter2 ) ) {
+ TimePosition begin = ( (GenericTimePeriod) ( (Literal>) parameter2 ).getValue() ).getBeginPosition();
+ TimePosition end = ( (GenericTimePeriod) ( (Literal>) parameter2 ).getValue() ).getEndPosition();
+ SQLExpression valueReference = toProtoSQL( op.getParameter1() );
+ SQLExpression beginExpr = createDateExpression( begin );
+ SQLExpression endExpr = createDateExpression( end );
+ sql = createSqlDuring( valueReference, beginExpr, endExpr );
+ }
+ break;
+ }
+ default:
+ sql = super.toProtoSQL( op );
+ }
+ return sql;
+ }
+
+ private SQLExpression createDateExpression( TimePosition timePosition ) {
+ if ( timePosition.getIndeterminatePosition() != null ) {
+ if ( timePosition.getIndeterminatePosition().equals( IndeterminateValue.NOW ) ) {
+ String encodedTemporal = ISO8601Converter.formatDateTime( new Date() );
+ TimePosition now = new TimePosition( null, null, null, encodedTemporal );
+ return createDateExpressionFromTimePosition( now );
+ } else {
+ return null;
+ }
+ }
+ return createDateExpressionFromTimePosition( timePosition );
+ }
+
+ private SQLExpression createDateExpressionFromTimePosition( TimePosition now ) {
+ PrimitiveValue value = new PrimitiveValue( now.getValue(), new PrimitiveType( DATE_TIME ) );
+ DefaultPrimitiveConverter converter = new DefaultPrimitiveConverter( new PrimitiveType( DATE_TIME ), null,
+ false );
+ return new SQLArgument( value, converter );
+ }
+
@Override
protected void addExpression( SQLOperationBuilder builder, SQLExpression expr, Boolean matchCase ) {
if ( matchCase == null || matchCase ) {
@@ -400,4 +497,79 @@ private SQLExpression toProtoSQL( Geometry geom, ICRS targetCRS, int srid )
throws FilterEvaluationException {
return new SQLArgument( geom, new PostGISGeometryConverter( null, targetCRS, "" + srid, useLegacyPredicates ) );
}
+
+ private SQLOperation createSqlDuring( SQLExpression valueReference, SQLExpression beginExpr,
+ SQLExpression endExpr ) {
+ if ( beginExpr == null && endExpr == null )
+ return null;
+ if ( beginExpr != null && endExpr == null ) {
+ SQLOperationBuilder builder = new SQLOperationBuilder( BOOLEAN );
+ builder.add( "(" );
+ addExpression( builder, valueReference );
+ builder.add( " >= " );
+ addExpression( builder, beginExpr );
+ builder.add( ")" );
+ return builder.toOperation();
+ }
+ if ( beginExpr == null && endExpr != null ) {
+ SQLOperationBuilder builder = new SQLOperationBuilder( BOOLEAN );
+ builder.add( "(" );
+ addExpression( builder, valueReference );
+ builder.add( " <= " );
+ addExpression( builder, endExpr );
+ builder.add( ")" );
+ return builder.toOperation();
+ }
+ inferType( valueReference, beginExpr, endExpr );
+ SQLOperationBuilder builder = new SQLOperationBuilder( BOOLEAN );
+ builder.add( "(" );
+ addExpression( builder, valueReference );
+ builder.add( " >= " );
+ addExpression( builder, beginExpr );
+ builder.add( " AND " );
+ addExpression( builder, valueReference );
+ builder.add( " <= " );
+ addExpression( builder, endExpr );
+ builder.add( ")" );
+ return builder.toOperation();
+ }
+
+ private SQLOperation createSqlEquals( SQLExpression first, SQLExpression second ) {
+ SQLOperationBuilder builder = new SQLOperationBuilder( BOOLEAN );
+ builder.add( "(" );
+ addExpression( builder, first );
+ builder.add( " = " );
+ addExpression( builder, second );
+ builder.add( ")" );
+ return builder.toOperation();
+ }
+
+ private SQLOperation createSqlBefore( SQLExpression first, SQLExpression second ) {
+ SQLOperationBuilder builder = new SQLOperationBuilder( BOOLEAN );
+ builder.add( "(" );
+ addExpression( builder, first );
+ builder.add( " < " );
+ addExpression( builder, second );
+ builder.add( ")" );
+ return builder.toOperation();
+ }
+
+ private SQLOperation createSqlAfter( SQLExpression first, SQLExpression second ) {
+ SQLOperationBuilder builder = new SQLOperationBuilder( BOOLEAN );
+ builder.add( "(" );
+ addExpression( builder, first );
+ builder.add( " > " );
+ addExpression( builder, second );
+ builder.add( ")" );
+ return builder.toOperation();
+ }
+
+ private boolean isTimePeriod( Expression parameter2 ) {
+ return parameter2 instanceof Literal && ( (Literal>) parameter2 ).getValue() instanceof GenericTimePeriod;
+ }
+
+ private boolean isTimeInstant( Expression parameter2 ) {
+ return parameter2 instanceof Literal && ( (Literal>) parameter2 ).getValue() instanceof GenericTimeInstant;
+ }
+
}
\ No newline at end of file