diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java index bb3d6f8847..66bcc33e96 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java @@ -45,7 +45,6 @@ import org.hibernate.query.TypedParameterValue; import org.hibernate.query.criteria.JpaExpression; import org.hibernate.query.internal.QueryOptionsImpl; import org.hibernate.query.sqm.SqmExpressible; -import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral; import org.hibernate.query.sqm.tree.expression.SqmLiteral; import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.select.SqmSelectStatement; @@ -133,10 +132,6 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract if ( expression instanceof SqmLiteral ) { fetchValue = ( (SqmLiteral) expression ).getLiteralValue(); } - else if ( expression instanceof SqmHqlNumericLiteral ) { - final SqmHqlNumericLiteral hqlNumericLiteral = (SqmHqlNumericLiteral) expression; - fetchValue = hqlNumericLiteral.getTypeCategory().parseLiteralValue( hqlNumericLiteral.getLiteralValue() ); - } else if ( expression instanceof SqmParameter ) { fetchValue = getParameterValue( (Parameter) expression ); if ( fetchValue == null ) { 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 545c3e5887..2fde605f81 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 @@ -5525,7 +5525,11 @@ public abstract class BaseSqmToSqlAstConverter extends Base return handleConvertedUnparsedNumericLiteral( numericLiteral, expressible ); } - return new UnparsedNumericLiteral<>( numericLiteral.getLiteralValue(), jdbcMapping ); + return new UnparsedNumericLiteral<>( + numericLiteral.getUnparsedLiteralValue(), + numericLiteral.getTypeCategory(), + jdbcMapping + ); } private Expression handleConvertedUnparsedNumericLiteral( @@ -5535,7 +5539,7 @@ public abstract class BaseSqmToSqlAstConverter extends Base final BasicValueConverter valueConverter = expressible.getJdbcMapping().getValueConverter(); assert valueConverter != null; - final Number parsedValue = numericLiteral.getTypeCategory().parseLiteralValue( numericLiteral.getLiteralValue() ); + final Number parsedValue = numericLiteral.getTypeCategory().parseLiteralValue( numericLiteral.getUnparsedLiteralValue() ); final Object sqlLiteralValue; if ( valueConverter.getDomainJavaType().isInstance( parsedValue ) ) { //noinspection unchecked @@ -6663,7 +6667,9 @@ public abstract class BaseSqmToSqlAstConverter extends Base //TODO: do we need to temporarily set appliedByUnit // to null before we recurse down the tree? // and what about scale? + inferrableTypeAccessStack.push( () -> null ); Expression magnitude = toSqlExpression( toDuration.getMagnitude().accept( this ) ); + inferrableTypeAccessStack.pop(); DurationUnit unit = (DurationUnit) toDuration.getUnit().accept( this ); // let's start by applying the propagated scale diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmHqlNumericLiteral.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmHqlNumericLiteral.java index 4613d0931f..557f52eea6 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmHqlNumericLiteral.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmHqlNumericLiteral.java @@ -31,7 +31,7 @@ import org.hibernate.type.descriptor.java.JavaType; * * @author Steve Ebersole */ -public class SqmHqlNumericLiteral extends AbstractSqmExpression { +public class SqmHqlNumericLiteral extends SqmLiteral { private final String literalValue; private final NumericTypeCategory typeCategory; @@ -52,10 +52,15 @@ public class SqmHqlNumericLiteral extends AbstractSqmExpressio this.typeCategory = typeCategory; } - public String getLiteralValue() { + public String getUnparsedLiteralValue() { return literalValue; } + @Override + public N getLiteralValue() { + return typeCategory.parseLiteralValue( literalValue ); + } + public NumericTypeCategory getTypeCategory() { return typeCategory; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmLiteral.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmLiteral.java index 303cf681b9..cc245c1aba 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmLiteral.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmLiteral.java @@ -67,12 +67,12 @@ public class SqmLiteral extends AbstractSqmExpression { @Override public String asLoggableText() { - return "Literal( " + value + ")"; + return "Literal( " + getLiteralValue() + ")"; } @Override public void appendHqlString(StringBuilder sb) { - appendHqlString( sb, getJavaTypeDescriptor(), value ); + appendHqlString( sb, getJavaTypeDescriptor(), getLiteralValue() ); } public static void appendHqlString(StringBuilder sb, JavaType javaType, T value) { 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 c985315c8c..693c9ddefb 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 @@ -6678,7 +6678,7 @@ public abstract class AbstractSqlAstTranslator implemen @Override public void visitUnparsedNumericLiteral(UnparsedNumericLiteral literal) { - appendSql( literal.getLiteralValue() ); + appendSql( literal.getUnparsedLiteralValue() ); } private void visitLiteral(Literal literal) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/UnparsedNumericLiteral.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/UnparsedNumericLiteral.java index 63ece8f7a9..ea849d43a6 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/UnparsedNumericLiteral.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/UnparsedNumericLiteral.java @@ -6,12 +6,18 @@ */ package org.hibernate.sql.ast.tree.expression; +import java.sql.PreparedStatement; +import java.sql.SQLException; + import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMappingContainer; import org.hibernate.query.sqm.sql.internal.DomainResultProducer; +import org.hibernate.query.sqm.tree.expression.NumericTypeCategory; import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlExpressionResolver; import org.hibernate.sql.ast.spi.SqlSelection; +import org.hibernate.sql.exec.spi.ExecutionContext; +import org.hibernate.sql.exec.spi.JdbcParameterBindings; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.basic.BasicResult; @@ -24,16 +30,38 @@ import org.hibernate.type.spi.TypeConfiguration; * * @author Steve Ebersole */ -public class UnparsedNumericLiteral implements Expression, DomainResultProducer { +public class UnparsedNumericLiteral implements Literal, DomainResultProducer { private final String literalValue; + private final NumericTypeCategory typeCategory; private final JdbcMapping jdbcMapping; - public UnparsedNumericLiteral(String literalValue, JdbcMapping jdbcMapping) { + public UnparsedNumericLiteral(String literalValue, NumericTypeCategory typeCategory, JdbcMapping jdbcMapping) { this.literalValue = literalValue; + this.typeCategory = typeCategory; this.jdbcMapping = jdbcMapping; } - public String getLiteralValue() { + @Override + public N getLiteralValue() { + return typeCategory.parseLiteralValue( literalValue ); + } + + @Override + public void bindParameterValue( + PreparedStatement statement, + int startPosition, + JdbcParameterBindings jdbcParameterBindings, + ExecutionContext executionContext) throws SQLException { + //noinspection unchecked + jdbcMapping.getJdbcValueBinder().bind( + statement, + getLiteralValue(), + startPosition, + executionContext.getSession() + ); + } + + public String getUnparsedLiteralValue() { return literalValue; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/WhereClauseTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/WhereClauseTests.java index f1996627ca..afb00aed13 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/WhereClauseTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/WhereClauseTests.java @@ -12,7 +12,6 @@ import org.hibernate.query.sqm.ComparisonOperator; import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.expression.SqmCollectionSize; import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral; -import org.hibernate.query.sqm.tree.expression.SqmLiteral; import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate; import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate; import org.hibernate.query.sqm.tree.predicate.SqmPredicate; @@ -82,7 +81,7 @@ public class WhereClauseTests extends BaseSqmUnitTest { assertThat( relationalPredicate.getSqmOperator(), is( ComparisonOperator.EQUAL ) ); assertThat( relationalPredicate.getRightHandExpression(), instanceOf( SqmHqlNumericLiteral.class ) ); - assertThat( ( (SqmHqlNumericLiteral) relationalPredicate.getRightHandExpression() ).getLiteralValue(), is( "311" ) ); + assertThat( ( (SqmHqlNumericLiteral) relationalPredicate.getRightHandExpression() ).getUnparsedLiteralValue(), is( "311" ) ); assertThat( relationalPredicate.getLeftHandExpression(), instanceOf( SqmCollectionSize.class ) ); @@ -102,7 +101,7 @@ public class WhereClauseTests extends BaseSqmUnitTest { assertThat( relationalPredicate.getSqmOperator(), is( ComparisonOperator.GREATER_THAN ) ); assertThat( relationalPredicate.getRightHandExpression(), instanceOf( SqmHqlNumericLiteral.class ) ); - assertThat( ( (SqmHqlNumericLiteral) relationalPredicate.getRightHandExpression() ).getLiteralValue(), is( "2" ) ); + assertThat( ( (SqmHqlNumericLiteral) relationalPredicate.getRightHandExpression() ).getUnparsedLiteralValue(), is( "2" ) ); assertThat( relationalPredicate.getLeftHandExpression(), instanceOf( SqmPath.class ) ); final SqmPath indexPath = (SqmPath) relationalPredicate.getLeftHandExpression(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/subquery/SubqueryTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/subquery/SubqueryTest.java index 9966aeb6c8..8c053f6448 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/subquery/SubqueryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/subquery/SubqueryTest.java @@ -61,7 +61,7 @@ public class SubqueryTest extends BaseSessionFactoryFunctionalTest { public void render( SqlAppender sqlAppender, List sqlAstArguments, SqlAstTranslator walker) { sqlAstArguments.get( 0 ).accept( walker ); - sqlAppender.appendSql( " limit " + ( (UnparsedNumericLiteral) sqlAstArguments.get( 1 ) ).getLiteralValue() ); + sqlAppender.appendSql( " limit " + ( (UnparsedNumericLiteral) sqlAstArguments.get( 1 ) ).getUnparsedLiteralValue() ); } }