Model timestampdiff with interval as result with null duration unit

This commit is contained in:
Christian Beikov 2022-03-22 18:27:31 +01:00
parent de21820f84
commit 6b8fdf3b70
6 changed files with 40 additions and 12 deletions

View File

@ -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))";

View File

@ -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)";
}

View File

@ -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

View File

@ -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
);
}

View File

@ -5453,10 +5453,20 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> 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<T extends Statement> 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 );
}
}

View File

@ -4439,10 +4439,12 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> 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