From 6b8fdf3b703a2f62d4fd99fc7d8222d4addbcad5 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Tue, 22 Mar 2022 18:27:31 +0100 Subject: [PATCH] Model timestampdiff with interval as result with null duration unit --- .../hibernate/dialect/CockroachDialect.java | 3 +++ .../java/org/hibernate/dialect/H2Dialect.java | 3 +++ .../hibernate/dialect/PostgreSQLDialect.java | 3 +++ .../function/TimestampdiffFunction.java | 7 +++-- .../sqm/sql/BaseSqmToSqlAstConverter.java | 26 ++++++++++++++----- .../sql/ast/spi/AbstractSqlAstTranslator.java | 10 ++++--- 6 files changed, 40 insertions(+), 12 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java index 397f9dbd46..24a18b6ad2 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java @@ -516,6 +516,9 @@ public class CockroachDialect extends Dialect { @Override public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalType, TemporalType toTemporalType) { + if ( unit == null ) { + return "(?3-?2)"; + } switch (unit) { case YEAR: return "(extract(year from ?3)-extract(year from ?2))"; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java index eb82149aaa..5674ebef65 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -398,6 +398,9 @@ public class H2Dialect extends Dialect { @Override public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalType, TemporalType toTemporalType) { + if ( unit == null ) { + return "(?3-?2)"; + } return "datediff(?1,?2,?3)"; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java index e7864445f9..24860a5401 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -330,6 +330,9 @@ public class PostgreSQLDialect extends Dialect { @Override public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalType, TemporalType toTemporalType) { + if ( unit == null ) { + return "(?3-?2)"; + } if ( toTemporalType != TemporalType.TIMESTAMP && fromTemporalType != TemporalType.TIMESTAMP && unit == DAY ) { // special case: subtraction of two dates // results in an integer number of days diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampdiffFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampdiffFunction.java index bb2a1d9195..ec338f98fb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampdiffFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampdiffFunction.java @@ -11,6 +11,7 @@ import java.util.function.Supplier; import org.hibernate.dialect.Dialect; import org.hibernate.metamodel.mapping.BasicValuedMapping; +import org.hibernate.metamodel.mapping.JdbcMappingContainer; import org.hibernate.query.ReturnableType; import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; @@ -79,7 +80,7 @@ public class TimestampdiffFunction final Expression from = (Expression) arguments.get( 1 ); final Expression to = (Expression) arguments.get( 2 ); - patternRenderer( field.getUnit(), from, to ).render( sqlAppender, arguments, walker ); + patternRenderer( field == null ? null : field.getUnit(), from, to ).render( sqlAppender, arguments, walker ); } private PatternRenderer patternRenderer(TemporalUnit unit, Expression from, Expression to) { @@ -99,7 +100,9 @@ public class TimestampdiffFunction impliedResultType != null ? impliedResultType : (ReturnableType) field.getExpressionType().getJdbcMapping(), - field.getExpressionType() + field != null + ? field.getExpressionType() + : (JdbcMappingContainer) impliedResultType ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java index 92d0070617..90f3074742 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java @@ -5453,10 +5453,20 @@ public abstract class BaseSqmToSqlAstConverter extends Base // the diff, and then the subsequent add DurationUnit unit = new DurationUnit( baseUnit, diffResultType ); - Expression magnitude = applyScale( timestampdiff().expression( null, unit, right, left ) ); + BasicValuedMapping durationType = (BasicValuedMapping) expression.getNodeType(); + Expression scaledMagnitude = applyScale( + timestampdiff().expression( + (ReturnableType) expression.getNodeType(), + durationType.getJdbcMapping().getJdbcType().isInterval() ? null : unit, + right, + left + ) + ); return timestampadd().expression( (ReturnableType) adjustedTimestampType, //TODO should be adjustedTimestamp.getType() - unit, magnitude, adjustedTimestamp + unit, + scaledMagnitude, + adjustedTimestamp ); } else if ( appliedByUnit != null ) { @@ -5470,10 +5480,14 @@ public abstract class BaseSqmToSqlAstConverter extends Base // a plain "bare" Duration DurationUnit unit = new DurationUnit( baseUnit, diffResultType ); BasicValuedMapping durationType = (BasicValuedMapping) expression.getNodeType(); - Expression scaledMagnitude = applyScale( timestampdiff().expression( - (ReturnableType) expression.getNodeType(), - unit, right, left - ) ); + Expression scaledMagnitude = applyScale( + timestampdiff().expression( + (ReturnableType) expression.getNodeType(), + durationType.getJdbcMapping().getJdbcType().isInterval() ? null : unit, + right, + left + ) + ); return new Duration( scaledMagnitude, baseUnit, durationType ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java index dc6ce8a1ae..3b813fa6b3 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java @@ -4439,10 +4439,12 @@ public abstract class AbstractSqlAstTranslator implemen @Override public void visitDuration(Duration duration) { duration.getMagnitude().accept( this ); - // Convert to NANOSECOND because DurationJavaType requires values in that unit - appendSql( - duration.getUnit().conversionFactor( NANOSECOND, getDialect() ) - ); + if ( !duration.getExpressionType().getJdbcMapping().getJdbcType().isInterval() ) { + // Convert to NANOSECOND because DurationJavaType requires values in that unit + appendSql( + duration.getUnit().conversionFactor( NANOSECOND, getDialect() ) + ); + } } @Override