HHH-17074 Type inference in duration arithmetic is wrong
This commit is contained in:
parent
10baf4398a
commit
6a56fc62e5
|
@ -6245,6 +6245,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
final BinaryArithmeticOperator operator = expression.getOperator();
|
final BinaryArithmeticOperator operator = expression.getOperator();
|
||||||
final SqmExpression<?> lhs = SqmExpressionHelper.getActualExpression( expression.getLeftHandOperand() );
|
final SqmExpression<?> lhs = SqmExpressionHelper.getActualExpression( expression.getLeftHandOperand() );
|
||||||
final SqmExpression<?> rhs = SqmExpressionHelper.getActualExpression( expression.getRightHandOperand() );
|
final SqmExpression<?> rhs = SqmExpressionHelper.getActualExpression( expression.getRightHandOperand() );
|
||||||
|
final FromClauseIndex fromClauseIndex = fromClauseIndexStack.getCurrent();
|
||||||
|
|
||||||
// we have a date or timestamp somewhere to
|
// we have a date or timestamp somewhere to
|
||||||
// the right of us, so we need to restructure
|
// the right of us, so we need to restructure
|
||||||
|
@ -6277,7 +6278,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
|
|
||||||
Expression timestamp = adjustedTimestamp;
|
Expression timestamp = adjustedTimestamp;
|
||||||
SqmExpressible<?> timestampType = adjustedTimestampType;
|
SqmExpressible<?> timestampType = adjustedTimestampType;
|
||||||
|
inferrableTypeAccessStack.push( () -> determineValueMapping( rhs, fromClauseIndex ) );
|
||||||
adjustedTimestamp = toSqlExpression( lhs.accept( this ) );
|
adjustedTimestamp = toSqlExpression( lhs.accept( this ) );
|
||||||
|
inferrableTypeAccessStack.pop();
|
||||||
JdbcMappingContainer type = adjustedTimestamp.getExpressionType();
|
JdbcMappingContainer type = adjustedTimestamp.getExpressionType();
|
||||||
if ( type instanceof SqmExpressible) {
|
if ( type instanceof SqmExpressible) {
|
||||||
adjustedTimestampType = (SqmExpressible<?>) type;
|
adjustedTimestampType = (SqmExpressible<?>) type;
|
||||||
|
@ -6293,6 +6296,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
negativeAdjustment = !negativeAdjustment;
|
negativeAdjustment = !negativeAdjustment;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
inferrableTypeAccessStack.push( () -> determineValueMapping( lhs, fromClauseIndex ) );
|
||||||
final Object result = rhs.accept( this );
|
final Object result = rhs.accept( this );
|
||||||
if ( result instanceof SqlTupleContainer ) {
|
if ( result instanceof SqlTupleContainer ) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -6324,6 +6328,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
inferrableTypeAccessStack.pop();
|
||||||
if ( operator == SUBTRACT ) {
|
if ( operator == SUBTRACT ) {
|
||||||
negativeAdjustment = !negativeAdjustment;
|
negativeAdjustment = !negativeAdjustment;
|
||||||
}
|
}
|
||||||
|
@ -6342,15 +6347,19 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
// x * (d1 - d2) => x * d1 - x * d2
|
// x * (d1 - d2) => x * d1 - x * d2
|
||||||
// -x * (d1 + d2) => - x * d1 - x * d2
|
// -x * (d1 + d2) => - x * d1 - x * d2
|
||||||
// -x * (d1 - d2) => - x * d1 + x * d2
|
// -x * (d1 - d2) => - x * d1 + x * d2
|
||||||
|
inferrableTypeAccessStack.push( () -> determineValueMapping( rhs, fromClauseIndex ) );
|
||||||
Expression duration = toSqlExpression( lhs.accept( this ) );
|
Expression duration = toSqlExpression( lhs.accept( this ) );
|
||||||
|
inferrableTypeAccessStack.pop();
|
||||||
Expression scale = adjustmentScale;
|
Expression scale = adjustmentScale;
|
||||||
boolean negate = negativeAdjustment;
|
boolean negate = negativeAdjustment;
|
||||||
adjustmentScale = applyScale( duration );
|
adjustmentScale = applyScale( duration );
|
||||||
negativeAdjustment = false; //was sucked into the scale
|
negativeAdjustment = false; //was sucked into the scale
|
||||||
try {
|
try {
|
||||||
|
inferrableTypeAccessStack.push( () -> determineValueMapping( lhs, fromClauseIndex ) );
|
||||||
return rhs.accept( this );
|
return rhs.accept( this );
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
inferrableTypeAccessStack.pop();
|
||||||
adjustmentScale = scale;
|
adjustmentScale = scale;
|
||||||
negativeAdjustment = negate;
|
negativeAdjustment = negate;
|
||||||
}
|
}
|
||||||
|
@ -6379,8 +6388,13 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
final SqmExpression<?> lhs = SqmExpressionHelper.getActualExpression( expression.getLeftHandOperand() );
|
final SqmExpression<?> lhs = SqmExpressionHelper.getActualExpression( expression.getLeftHandOperand() );
|
||||||
final SqmExpression<?> rhs = SqmExpressionHelper.getActualExpression( expression.getRightHandOperand() );
|
final SqmExpression<?> rhs = SqmExpressionHelper.getActualExpression( expression.getRightHandOperand() );
|
||||||
|
|
||||||
Expression left = getActualExpression( cleanly( () -> toSqlExpression( lhs.accept( this ) ) ) );
|
final FromClauseIndex fromClauseIndex = fromClauseIndexStack.getCurrent();
|
||||||
Expression right = getActualExpression( cleanly( () -> toSqlExpression( rhs.accept( this ) ) ) );
|
inferrableTypeAccessStack.push( () -> determineValueMapping( rhs, fromClauseIndex ) );
|
||||||
|
final Expression left = getActualExpression( cleanly( () -> toSqlExpression( lhs.accept( this ) ) ) );
|
||||||
|
inferrableTypeAccessStack.pop();
|
||||||
|
inferrableTypeAccessStack.push( () -> determineValueMapping( lhs, fromClauseIndex ) );
|
||||||
|
final Expression right = getActualExpression( cleanly( () -> toSqlExpression( rhs.accept( this ) ) ) );
|
||||||
|
inferrableTypeAccessStack.pop();
|
||||||
|
|
||||||
// The result of timestamp subtraction is always a `Duration`, unless a unit is applied
|
// The result of timestamp subtraction is always a `Duration`, unless a unit is applied
|
||||||
// So use SECOND granularity with fractions as that is what the `DurationJavaType` expects
|
// So use SECOND granularity with fractions as that is what the `DurationJavaType` expects
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.testing.orm.domain.gambit.EntityOfMaps;
|
||||||
import org.hibernate.testing.orm.domain.gambit.SimpleEntity;
|
import org.hibernate.testing.orm.domain.gambit.SimpleEntity;
|
||||||
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.JiraKey;
|
||||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||||
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
@ -1406,6 +1407,22 @@ public class FunctionTests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@JiraKey("HHH-17074")
|
||||||
|
public void testDurationArithmeticWithParameters(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
assertEquals(
|
||||||
|
1,
|
||||||
|
session.createQuery( "from EntityOfBasics e where (:date - e.theTimestamp) by day > 1" )
|
||||||
|
.setParameter( "date", Timestamp.valueOf( "2022-01-01 00:00:00" ) )
|
||||||
|
.getResultList()
|
||||||
|
.size()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIntervalDiffExpressions(SessionFactoryScope scope) {
|
public void testIntervalDiffExpressions(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
|
|
Loading…
Reference in New Issue