Skip to content

Commit ab4ac5a

Browse files
committed
HHH-17076 - Numeric literal typing
https://hibernate.atlassian.net/browse/HHH-17076
1 parent c7ed34d commit ab4ac5a

20 files changed

+503
-289
lines changed

hibernate-core/src/main/antlr/org/hibernate/grammars/hql/HqlLexer.g4

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ INTEGER_LITERAL : INTEGER_NUMBER ('_' INTEGER_NUMBER)*;
6262

6363
LONG_LITERAL : INTEGER_NUMBER ('_' INTEGER_NUMBER)* LONG_SUFFIX;
6464

65-
FLOAT_LITERAL : FLOATING_POINT_NUMBER FLOAT_SUFFIX?;
65+
FLOAT_LITERAL : FLOATING_POINT_NUMBER FLOAT_SUFFIX;
6666

67-
DOUBLE_LITERAL : FLOATING_POINT_NUMBER DOUBLE_SUFFIX;
67+
DOUBLE_LITERAL : FLOATING_POINT_NUMBER DOUBLE_SUFFIX?;
6868

6969
BIG_INTEGER_LITERAL : INTEGER_NUMBER BIG_INTEGER_SUFFIX;
7070

hibernate-core/src/main/antlr/org/hibernate/grammars/hql/HqlParser.g4

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,7 @@ parameterOrIntegerLiteral
611611
parameterOrNumberLiteral
612612
: parameter
613613
| INTEGER_LITERAL
614+
| LONG_LITERAL
614615
| FLOAT_LITERAL
615616
| DOUBLE_LITERAL
616617
;
@@ -1006,7 +1007,7 @@ month: INTEGER_LITERAL;
10061007
day: INTEGER_LITERAL;
10071008
hour: INTEGER_LITERAL;
10081009
minute: INTEGER_LITERAL;
1009-
second: INTEGER_LITERAL | FLOAT_LITERAL;
1010+
second: INTEGER_LITERAL | DOUBLE_LITERAL;
10101011
zoneId
10111012
: IDENTIFIER (SLASH IDENTIFIER)?
10121013
| STRING_LITERAL;

hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java

Lines changed: 57 additions & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@
145145
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
146146
import org.hibernate.query.sqm.tree.expression.SqmFormat;
147147
import org.hibernate.query.sqm.tree.expression.SqmFunction;
148+
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
148149
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
149150
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
150151
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
@@ -1791,7 +1792,7 @@ public SqmExpression<?> visitFunctionExpression(HqlParser.FunctionExpressionCont
17911792
@Override
17921793
public SqmExpression<?> visitParameterOrIntegerLiteral(HqlParser.ParameterOrIntegerLiteralContext ctx) {
17931794
if ( ctx.INTEGER_LITERAL() != null ) {
1794-
return integralLiteral( ctx.INTEGER_LITERAL().getText() );
1795+
return integerLiteral( ctx.INTEGER_LITERAL().getText() );
17951796
}
17961797
else {
17971798
return (SqmExpression<?>) ctx.parameter().accept( this );
@@ -1801,10 +1802,10 @@ public SqmExpression<?> visitParameterOrIntegerLiteral(HqlParser.ParameterOrInte
18011802
@Override
18021803
public SqmExpression<?> visitParameterOrNumberLiteral(HqlParser.ParameterOrNumberLiteralContext ctx) {
18031804
if ( ctx.INTEGER_LITERAL() != null ) {
1804-
return integralLiteral( ctx.INTEGER_LITERAL().getText() );
1805+
return integerLiteral( ctx.INTEGER_LITERAL().getText() );
18051806
}
18061807
if ( ctx.FLOAT_LITERAL() != null ) {
1807-
return numericLiteral( ctx.FLOAT_LITERAL().getText() );
1808+
return floatLiteral( ctx.FLOAT_LITERAL().getText() );
18081809
}
18091810
if ( ctx.DOUBLE_LITERAL() != null ) {
18101811
return doubleLiteral( ctx.DOUBLE_LITERAL().getText() );
@@ -1816,9 +1817,9 @@ public SqmExpression<?> visitParameterOrNumberLiteral(HqlParser.ParameterOrNumbe
18161817
if ( firstChild instanceof TerminalNode ) {
18171818
switch ( ( (TerminalNode) firstChild ).getSymbol().getType() ) {
18181819
case HqlParser.INTEGER_LITERAL:
1819-
return integralLiteral( firstChild.getText() );
1820+
return integerLiteral( firstChild.getText() );
18201821
case HqlParser.FLOAT_LITERAL:
1821-
return numericLiteral( firstChild.getText() );
1822+
return floatLiteral( firstChild.getText() );
18221823
case HqlParser.DOUBLE_LITERAL:
18231824
return doubleLiteral( firstChild.getText() );
18241825
default:
@@ -3224,15 +3225,15 @@ public SqmExpression<?> visitUnaryNumericLiteralExpression(HqlParser.UnaryNumeri
32243225
}
32253226
switch ( node.getSymbol().getType() ) {
32263227
case HqlParser.INTEGER_LITERAL:
3227-
return integralLiteral( text );
3228+
return integerLiteral( text );
32283229
case HqlParser.LONG_LITERAL:
32293230
return longLiteral( text );
32303231
case HqlParser.BIG_INTEGER_LITERAL:
32313232
return bigIntegerLiteral( text );
32323233
case HqlParser.HEX_LITERAL:
32333234
return hexLiteral( text );
32343235
case HqlParser.FLOAT_LITERAL:
3235-
return numericLiteral( text );
3236+
return floatLiteral( text );
32363237
case HqlParser.DOUBLE_LITERAL:
32373238
return doubleLiteral( text );
32383239
case HqlParser.BIG_DECIMAL_LITERAL:
@@ -3281,15 +3282,15 @@ public SqmExpression<?> visitTerminal(TerminalNode node) {
32813282
case HqlParser.JAVA_STRING_LITERAL:
32823283
return javaStringLiteral( node.getText() );
32833284
case HqlParser.INTEGER_LITERAL:
3284-
return integralLiteral( node.getText() );
3285+
return integerLiteral( node.getText() );
32853286
case HqlParser.LONG_LITERAL:
32863287
return longLiteral( node.getText() );
32873288
case HqlParser.BIG_INTEGER_LITERAL:
32883289
return bigIntegerLiteral( node.getText() );
32893290
case HqlParser.HEX_LITERAL:
32903291
return hexLiteral( node.getText() );
32913292
case HqlParser.FLOAT_LITERAL:
3292-
return numericLiteral( node.getText() );
3293+
return floatLiteral( node.getText() );
32933294
case HqlParser.DOUBLE_LITERAL:
32943295
return doubleLiteral( node.getText() );
32953296
case HqlParser.BIG_DECIMAL_LITERAL:
@@ -3621,235 +3622,67 @@ private SqmLiteral<byte[]> binaryLiteral(String text) {
36213622
);
36223623
}
36233624

3624-
private SqmLiteral<? extends Number> integralLiteral(String text) {
3625-
final String integralText = text.replace( "_", "" );
3626-
final int decimalNumbers = integralText.length() - ( integralText.charAt( 0 ) == '-' ? 1 : 0 );
3627-
if ( decimalNumbers > 19 ) {
3628-
try {
3629-
final BigInteger value = new BigInteger( integralText );
3630-
return new SqmLiteral<>(
3631-
value,
3632-
resolveExpressibleTypeBasic( BigInteger.class ),
3633-
creationContext.getNodeBuilder()
3634-
);
3635-
}
3636-
catch (NumberFormatException e) {
3637-
throw new LiteralNumberFormatException(
3638-
"Unable to convert sqm literal [" + text + "] to BigInteger",
3639-
e
3640-
);
3641-
}
3642-
}
3643-
else if ( decimalNumbers > 10 ) {
3644-
try {
3645-
final Long value = Long.valueOf( integralText );
3646-
return new SqmLiteral<>(
3647-
value,
3648-
resolveExpressibleTypeBasic( Long.class ),
3649-
creationContext.getNodeBuilder()
3650-
);
3651-
}
3652-
catch (NumberFormatException e) {
3653-
try {
3654-
final BigInteger value = new BigInteger( integralText );
3655-
return new SqmLiteral<>(
3656-
value,
3657-
resolveExpressibleTypeBasic( BigInteger.class ),
3658-
creationContext.getNodeBuilder()
3659-
);
3660-
}
3661-
catch (NumberFormatException e2) {
3662-
final LiteralNumberFormatException exception = new LiteralNumberFormatException(
3663-
"Unable to convert sqm literal [" + text + "] to Long or BigInteger",
3664-
e
3665-
);
3666-
exception.addSuppressed( e );
3667-
exception.addSuppressed( e2 );
3668-
throw exception;
3669-
}
3670-
}
3671-
}
3672-
try {
3673-
final Integer value = Integer.valueOf( integralText );
3674-
return new SqmLiteral<>(
3675-
value,
3676-
resolveExpressibleTypeBasic( Integer.class ),
3677-
creationContext.getNodeBuilder()
3678-
);
3679-
}
3680-
catch (NumberFormatException e) {
3681-
try {
3682-
final Long value = Long.valueOf( integralText );
3683-
return new SqmLiteral<>(
3684-
value,
3685-
resolveExpressibleTypeBasic( Long.class ),
3686-
creationContext.getNodeBuilder()
3687-
);
3688-
}
3689-
catch (NumberFormatException e2) {
3690-
try {
3691-
final BigInteger value = new BigInteger( integralText );
3692-
return new SqmLiteral<>(
3693-
value,
3694-
resolveExpressibleTypeBasic( BigInteger.class ),
3695-
creationContext.getNodeBuilder()
3696-
);
3697-
}
3698-
catch (NumberFormatException e3) {
3699-
final LiteralNumberFormatException exception = new LiteralNumberFormatException(
3700-
"Unable to convert sqm literal [" + text + "] to Integer, Long or BigInteger",
3701-
e
3702-
);
3703-
exception.addSuppressed( e );
3704-
exception.addSuppressed( e2 );
3705-
exception.addSuppressed( e3 );
3706-
throw exception;
3707-
}
3708-
}
3709-
}
3625+
private SqmHqlNumericLiteral<Integer> integerLiteral(String text) {
3626+
return new SqmHqlNumericLiteral<>(
3627+
text.replace( "_", "" ),
3628+
integerDomainType,
3629+
creationContext.getNodeBuilder()
3630+
);
37103631
}
37113632

3712-
private SqmLiteral<Long> longLiteral(String text) {
3713-
final String originalText = text;
3714-
try {
3715-
if ( text.endsWith( "l" ) || text.endsWith( "L" ) ) {
3716-
text = text.substring( 0, text.length() - 1 ).replace("_", "");
3717-
}
3718-
final Long value = Long.valueOf( text );
3719-
return new SqmLiteral<>(
3720-
value,
3721-
resolveExpressibleTypeBasic( Long.class ),
3722-
creationContext.getNodeBuilder()
3723-
);
3724-
}
3725-
catch (NumberFormatException e) {
3726-
throw new LiteralNumberFormatException(
3727-
"Unable to convert sqm literal [" + originalText + "] to Long",
3728-
e
3729-
);
3730-
}
3633+
private SqmHqlNumericLiteral<Long> longLiteral(String text) {
3634+
assert text.endsWith( "l" ) || text.endsWith( "L" );
3635+
return new SqmHqlNumericLiteral<>(
3636+
text.substring( 0, text.length() - 1 ).replace( "_", "" ),
3637+
resolveExpressibleTypeBasic( Long.class ),
3638+
creationContext.getNodeBuilder()
3639+
);
37313640
}
37323641

3733-
private SqmLiteral<? extends Number> hexLiteral(String text) {
3734-
final String originalText = text;
3735-
text = text.substring( 2 );
3736-
try {
3737-
if ( text.endsWith( "l" ) || text.endsWith( "L" ) ) {
3738-
text = text.substring( 0, text.length() - 1 );
3739-
final long value = Long.parseUnsignedLong( text, 16 );
3740-
return new SqmLiteral<>(
3741-
value,
3742-
resolveExpressibleTypeBasic( Long.class ),
3743-
creationContext.getNodeBuilder()
3744-
);
3745-
}
3746-
else {
3747-
final int value = Integer.parseUnsignedInt( text, 16 );
3748-
return new SqmLiteral<>(
3749-
value,
3750-
resolveExpressibleTypeBasic( Integer.class ),
3751-
creationContext.getNodeBuilder()
3752-
);
3753-
}
3754-
}
3755-
catch (NumberFormatException e) {
3756-
throw new LiteralNumberFormatException(
3757-
"Unable to convert sqm literal [" + originalText + "]",
3758-
e
3759-
);
3760-
}
3642+
private SqmHqlNumericLiteral<BigInteger> bigIntegerLiteral(String text) {
3643+
assert text.endsWith( "bi" ) || text.endsWith( "BI" );
3644+
return new SqmHqlNumericLiteral<>(
3645+
text.substring( 0, text.length() - 2 ).replace( "_", "" ),
3646+
resolveExpressibleTypeBasic( BigInteger.class ),
3647+
creationContext.getNodeBuilder()
3648+
);
37613649
}
37623650

3763-
private SqmLiteral<BigInteger> bigIntegerLiteral(String text) {
3764-
final String originalText = text;
3765-
try {
3766-
if ( text.endsWith( "bi" ) || text.endsWith( "BI" ) ) {
3767-
text = text.substring( 0, text.length() - 2 );
3768-
}
3769-
return new SqmLiteral<>(
3770-
new BigInteger( text ),
3771-
resolveExpressibleTypeBasic( BigInteger.class ),
3772-
creationContext.getNodeBuilder()
3773-
);
3774-
}
3775-
catch (NumberFormatException e) {
3776-
throw new LiteralNumberFormatException(
3777-
"Unable to convert sqm literal [" + originalText + "] to BigInteger",
3778-
e
3779-
);
3780-
}
3651+
private SqmHqlNumericLiteral<? extends Number> floatLiteral(String text) {
3652+
assert text.endsWith( "f" ) || text.endsWith( "F" );
3653+
return new SqmHqlNumericLiteral<>(
3654+
text.substring( 0, text.length() - 1 ).replace( "_", "" ),
3655+
resolveExpressibleTypeBasic( Float.class ),
3656+
creationContext.getNodeBuilder()
3657+
);
37813658
}
37823659

3783-
private SqmLiteral<? extends Number> numericLiteral(String text) {
3784-
final String numericText = text.replace( "_", "" );
3785-
final char lastChar = text.charAt( text.length() - 1 );
3786-
if ( lastChar == 'f' || lastChar == 'F' ) {
3787-
try {
3788-
return new SqmLiteral<>(
3789-
Float.valueOf( numericText ),
3790-
resolveExpressibleTypeBasic( Float.class ),
3791-
creationContext.getNodeBuilder()
3792-
);
3793-
}
3794-
catch (NumberFormatException e) {
3795-
throw new LiteralNumberFormatException(
3796-
"Unable to convert sqm literal [" + text + "] to Float",
3797-
e
3798-
);
3799-
}
3800-
}
3801-
else {
3802-
// Treat numeric literals without a type suffix like BigDecimal
3803-
// according to the JPA spec 4.6.1 and SQL spec 5.3
3804-
try {
3805-
return new SqmLiteral<>(
3806-
new BigDecimal( numericText ),
3807-
resolveExpressibleTypeBasic( BigDecimal.class ),
3808-
creationContext.getNodeBuilder()
3809-
);
3810-
}
3811-
catch (NumberFormatException e) {
3812-
throw new LiteralNumberFormatException(
3813-
"Unable to convert sqm literal [" + text + "] to BigDecimal",
3814-
e
3815-
);
3816-
}
3660+
private SqmHqlNumericLiteral<Double> doubleLiteral(String text) {
3661+
if ( text.endsWith( "d" ) || text.endsWith( "D" ) ) {
3662+
text = text.substring( 0, text.length() - 1 );
38173663
}
3664+
return new SqmHqlNumericLiteral<>(
3665+
text.replace( "_", "" ),
3666+
resolveExpressibleTypeBasic( Double.class ),
3667+
creationContext.getNodeBuilder()
3668+
);
38183669
}
38193670

3820-
private SqmLiteral<Double> doubleLiteral(String text) {
3821-
try {
3822-
return new SqmLiteral<>(
3823-
Double.valueOf( text ),
3824-
resolveExpressibleTypeBasic( Double.class ),
3825-
creationContext.getNodeBuilder()
3826-
);
3827-
}
3828-
catch (NumberFormatException e) {
3829-
throw new LiteralNumberFormatException(
3830-
"Unable to convert sqm literal [" + text + "] to Double",
3831-
e
3832-
);
3833-
}
3671+
private SqmHqlNumericLiteral<BigDecimal> bigDecimalLiteral(String text) {
3672+
assert text.endsWith( "bd" ) || text.endsWith( "BD" );
3673+
return new SqmHqlNumericLiteral<>(
3674+
text.substring( 0, text.length() - 2 ).replace( "_", "" ),
3675+
resolveExpressibleTypeBasic( BigDecimal.class ),
3676+
creationContext.getNodeBuilder()
3677+
);
38343678
}
38353679

3836-
private SqmLiteral<BigDecimal> bigDecimalLiteral(String text) {
3837-
final String originalText = text;
3838-
try {
3839-
if ( text.endsWith( "bd" ) || text.endsWith( "BD" ) ) {
3840-
text = text.substring( 0, text.length() - 2 );
3841-
}
3842-
return new SqmLiteral<>(
3843-
new BigDecimal( text ),
3844-
resolveExpressibleTypeBasic( BigDecimal.class ),
3845-
creationContext.getNodeBuilder()
3846-
);
3680+
private SqmHqlNumericLiteral<? extends Number> hexLiteral(String text) {
3681+
if ( text.endsWith( "l" ) || text.endsWith( "L" ) ) {
3682+
return longLiteral( text );
38473683
}
3848-
catch (NumberFormatException e) {
3849-
throw new LiteralNumberFormatException(
3850-
"Unable to convert sqm literal [" + originalText + "] to BigDecimal",
3851-
e
3852-
);
3684+
else {
3685+
return integerLiteral( text );
38533686
}
38543687
}
38553688

0 commit comments

Comments
 (0)