[JIRA] (HHH-16738) BadJpqlGrammarException when using column names coinciding with functions in projection
by Niklas Fischer (JIRA)
Niklas Fischer ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=712020%... ) *created* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiN2FkZTc0YTEw... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16738?atlOrigin=eyJpIjoiN2FkZT... ) HHH-16738 ( https://hibernate.atlassian.net/browse/HHH-16738?atlOrigin=eyJpIjoiN2FkZT... ) BadJpqlGrammarException when using column names coinciding with functions in projection ( https://hibernate.atlassian.net/browse/HHH-16738?atlOrigin=eyJpIjoiN2FkZT... )
Issue Type: Bug Affects Versions: 6.2.2 Assignee: Unassigned Created: 01/Jun/2023 09:25 AM Environment: [INFO] | +- org.hibernate.orm:hibernate-core:jar:6.2.2.Final:compile
[INFO] | | +- jakarta.persistence:jakarta.persistence-api:jar:3.1.0:compile
[INFO] | | +- jakarta.transaction:jakarta.transaction-api:jar:2.0.1:compile
[INFO] | | +- org.hibernate.common:hibernate-commons-annotations:jar:6.0.6.Final:runtime
[INFO] | | +- io.smallrye:jandex:jar:3.0.5:runtime
[INFO] | | +- net.bytebuddy:byte-buddy:jar:1.14.4:runtime
[INFO] | | +- org.glassfish.jaxb:jaxb-runtime:jar:4.0.2:runtime
[INFO] | | | \- org.glassfish.jaxb:jaxb-core:jar:4.0.2:runtime
[INFO] | | | +- org.glassfish.jaxb:txw2:jar:4.0.2:runtime
[INFO] | | | \- com.sun.istack:istack-commons-runtime:jar:4.1.1:runtime
[INFO] | | +- jakarta.inject:jakarta.inject-api:jar:2.0.1:runtime
[INFO] | | \- org.antlr:antlr4-runtime:jar:4.10.1:compile
java --version
openjdk 20.0.1 2023-04-18
OpenJDK Runtime Environment (Red_Hat-20.0.1.0.9-2.rolling.fc38) (build 20.0.1+9)
OpenJDK 64-Bit Server VM (Red_Hat-20.0.1.0.9-2.rolling.fc38) (build 20.0.1+9, mixed mode, sharing)
storage_db=# select version();
version
-----------------------------------------------------------------------------------------------------------------------------
PostgreSQL 14.7 (Debian 14.7-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
Priority: Major Reporter: Niklas Fischer ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=712020%... )
Summary: I am unable to use columns with names identical to function names in projections.
Context:
Given I have an entity with a column called `sign`:
@Entity
@Table(name = "test" )
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class TestEntity{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "task_id" , nullable = false , updatable = false )
private UUID taskId;
@Column(name = "title" , nullable = false )
private boolean sign;
}
With a pojo defined that I want to project into:
public class TestProjection {
private boolean title;
public TestProjection( boolean title){
this.title = title;
}
}
Now, defining and running the following jpql query
public interface TestRepository extends JpaRepository<TestEntity, UUID> {
@Query(
"""
select new some.entity.TestProjection(
t.sign
)
from TestEntity t
"""
)
List<TestProjection> getAll();
}
leads to an exception
org.springframework.dao.InvalidDataAccessApiUsageException: org.springframework.data.jpa.repository.query.BadJpqlGrammarException: Line 2:10 no viable alternative at input 't.sign' ; Bad JPQL grammar [ select new some.entity.TestProjection(
t.sign
)
from TestEntity t
]
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:371)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:234)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:134)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
at jdk.proxy2/jdk.proxy2.$Proxy307.getAll(Unknown Source)
at some.TestEntityTest.test(TestEntityTest.java:27)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Caused by: java.lang.IllegalArgumentException: org.springframework.data.jpa.repository.query.BadJpqlGrammarException: Line 2:10 no viable alternative at input 't.sign' ; Bad JPQL grammar [ select new some.entity.TestProjection(
t.sign
)
from TestEntity t
]
at org.springframework.data.jpa.repository.query.JpaQueryParserSupport.renderSortedQuery(JpaQueryParserSupport.java:56)
at org.springframework.data.jpa.repository.query.JpaQueryEnhancer.applySorting(JpaQueryEnhancer.java:88)
at org.springframework.data.jpa.repository.query.JpaQueryEnhancer.applySorting(JpaQueryEnhancer.java:100)
at org.springframework.data.jpa.repository.query.AbstractStringBasedJpaQuery.doCreateQuery(AbstractStringBasedJpaQuery.java:96)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.createQuery(AbstractJpaQuery.java:234)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:129)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:92)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:148)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:136)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:77)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
... 76 more
Caused by: org.springframework.data.jpa.repository.query.BadJpqlGrammarException: Line 2:10 no viable alternative at input 't.sign' ; Bad JPQL grammar [ select new some.entity.TestProjection(
t.sign
)
from TestEntity t
]
at org.springframework.data.jpa.repository.query.BadJpqlGrammarErrorListener.syntaxError(BadJpqlGrammarErrorListener.java:39)
at org.antlr.v4.runtime.ProxyErrorListener.syntaxError(ProxyErrorListener.java:41)
at org.antlr.v4.runtime.Parser.notifyErrorListeners(Parser.java:543)
at org.antlr.v4.runtime.DefaultErrorStrategy.reportNoViableAlternative(DefaultErrorStrategy.java:310)
at org.antlr.v4.runtime.DefaultErrorStrategy.reportError(DefaultErrorStrategy.java:136)
at org.springframework.data.jpa.repository.query.HqlParser.expressionOrPredicate(HqlParser.java:8356)
at org.springframework.data.jpa.repository.query.HqlParser.instantiationArgument(HqlParser.java:9229)
at org.springframework.data.jpa.repository.query.HqlParser.instantiationArguments(HqlParser.java:9157)
at org.springframework.data.jpa.repository.query.HqlParser.instantiation(HqlParser.java:2395)
at org.springframework.data.jpa.repository.query.HqlParser.selectExpression(HqlParser.java:3275)
at org.springframework.data.jpa.repository.query.HqlParser.selection(HqlParser.java:3208)
at org.springframework.data.jpa.repository.query.HqlParser.selectionList(HqlParser.java:3145)
at org.springframework.data.jpa.repository.query.HqlParser.selectClause(HqlParser.java:3097)
at org.springframework.data.jpa.repository.query.HqlParser.query(HqlParser.java:633)
at org.springframework.data.jpa.repository.query.HqlParser.orderedQuery(HqlParser.java:507)
at org.springframework.data.jpa.repository.query.HqlParser.queryExpression(HqlParser.java:434)
at org.springframework.data.jpa.repository.query.HqlParser.selectStatement(HqlParser.java:380)
at org.springframework.data.jpa.repository.query.HqlParser.ql_statement(HqlParser.java:311)
at org.springframework.data.jpa.repository.query.HqlParser.start(HqlParser.java:250)
at org.springframework.data.jpa.repository.query.HqlQueryParser.parseQuery(HqlQueryParser.java:53)
at org.springframework.data.jpa.repository.query.HqlQueryParser.parse(HqlQueryParser.java:63)
at org.springframework.data.jpa.repository.query.JpaQueryParserSupport$ParseState.lambda$ new $0(JpaQueryParserSupport.java:182)
at org.springframework.data.util.Lazy.getNullable(Lazy.java:245)
at org.springframework.data.util.Lazy.get(Lazy.java:114)
at org.springframework.data.jpa.repository.query.JpaQueryParserSupport$ParseState.getContext(JpaQueryParserSupport.java:194)
at org.springframework.data.jpa.repository.query.JpaQueryParserSupport.renderSortedQuery(JpaQueryParserSupport.java:54)
... 96 more
18:06:09.049 W [utdownHook] o.s.b.f.s.DisposableBeanAdapter | : Invocation of close method failed on bean with name 'getAllocator' : java.lang.IllegalStateException: Shutdown in progress
Disconnected from the target VM, address: '127.0.0.1:45117' , transport: 'socket'
Process finished with exit code 255
I would expect it to resolve `t.sign` to be the `sign` property of the `TestEntity` what I think is what really happens is that `sign` is resolved to be the `sign()` function (i.e. `sign(-10) = -1`).
A similar exception occurs, when the column gets renamed to other popular function names such as `log` or `exp`. Renaming the column to `signing` leads to the query working as expected.
( https://hibernate.atlassian.net/browse/HHH-16738#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16738#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100225- sha1:40c4da4 )
2 years, 10 months
[JIRA] (HHH-16737) Interpretation of numeric literals without explicit type suffix
by Marcus Klimstra (JIRA)
Marcus Klimstra ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *updated* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiNzczMjVmY2Zi... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16737?atlOrigin=eyJpIjoiNzczMj... ) HHH-16737 ( https://hibernate.atlassian.net/browse/HHH-16737?atlOrigin=eyJpIjoiNzczMj... ) Interpretation of numeric literals without explicit type suffix ( https://hibernate.atlassian.net/browse/HHH-16737?atlOrigin=eyJpIjoiNzczMj... )
Change By: Marcus Klimstra ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
This could be either a documentation or implementation issue.
Section “16.3.3. Numeric literals” of the documentation shows some examples of numeric literals, with and without explicit type suffixes:
* “1” is indicated as a “simple integer literal”;
* “1L” is a “simple integer literal, typed as a long”;
* “100.5” is “decimal notation”;
* “100.5F” is “decimal notation, typed as a float”;
* “1e+2” is “scientific notation”;
* “1e+2F” is “scientific notation, typed as a float”.
It also states that “It’s not usually necessary to specify the precision explicitly.”
The problem I have with this is that it does not state how literals are interpreted when the type suffix is not specified.
My initial reading was that “100.5” would be interpreted as a BigDecimal. This is because the term “decimal” itself is a bit ambiguous, and the example is distinguished from the next one, which is indicated as “typed as float”.
However, it seems that it is in fact interpreted as float. I ran into this with a JPQL query containing a literal value that cannot be exactly represented as a float:
{{SELECT b.isbn, b.title, b.score FROM Book b WHERE b.score = 199999.99}}
Which is translated to the following SQL:
{{select b1_0.ISBN_,b1_0.TITLE_,b1_0.SCORE_ from BOOK b1_0 where b1_0.SCORE_=199999.98}}
(Note that Book.score is a BigDecimal in the Java model class)
So IMO it would help if the documentation would explicitly state how such literals are interpreted. One might also wonder if float (rather than say, double) is a good default representation. In Java, according to the JLS Section 3.10.2, "Floating-Point Literals," a floating-point literal without a suffix is of type {{double}} by default. The JPA 3.1 spec states that “Approximate literals support the use Java floating point literal syntax as well as SQL approximate numeric literal syntax.” This would suggest to me that {{double}} should be the default for JPQL as well.
( https://hibernate.atlassian.net/browse/HHH-16737#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16737#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100225- sha1:40c4da4 )
2 years, 10 months
[JIRA] (HHH-16737) Interpretation of numeric literals without explicit type suffix
by Marcus Klimstra (JIRA)
Marcus Klimstra ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *updated* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiMWU5N2ZiYTEy... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16737?atlOrigin=eyJpIjoiMWU5N2... ) HHH-16737 ( https://hibernate.atlassian.net/browse/HHH-16737?atlOrigin=eyJpIjoiMWU5N2... ) Interpretation of numeric literals without explicit type suffix ( https://hibernate.atlassian.net/browse/HHH-16737?atlOrigin=eyJpIjoiMWU5N2... )
Change By: Marcus Klimstra ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
This could be either a documentation or implementation issue.
Section “16.3.3. Numeric literals” of the documentation shows some examples of numeric literals, with and without explicit type suffixes:
* “1” is indicated as a “simple integer literal”;
* “1L” is a “simple integer literal, typed as a long”;
* “100.5” is “decimal notation”;
* “100.5F” is “decimal notation, typed as a float”;
* “1e+2” is “scientific notation”;
* “1e+2F” is “scientific notation, typed as a float”.
It also states that “It’s not usually necessary to specify the precision explicitly.”
The problem I have with this is that it does not state how literals are interpreted when the type suffix is not specified.
My initial reading was that “100.5” would be interpreted as a BigDecimal. This is because the term “decimal” itself is a bit ambiguous, and the example is distinguished from the next one, which is indicated as “typed as float”.
However, it seems that it is in fact interpreted as float. I ran into this with a JPQL query containing a literal value that cannot be exactly represented as a float:
{{SELECT b.isbn, b.title, b.score FROM Book b WHERE b.score = 199999.99}}
Is Which is translated to SQL :
{{select b1_0.ISBN_,b1_0.TITLE_,b1_0.SCORE_ from BOOK b1_0 where b1_0.SCORE_=199999.98}}
(Note that Book.score is a BigDecimal in the Java model class)
So IMO it would help if the documentation would explicitly state how such literals are interpreted. One might also wonder if float (rather than say, double) is a good default representation. In Java, according to the JLS Section 3.10.2, "Floating-Point Literals," a floating-point literal without a suffix is of type {{double}} by default. The JPA 3.1 spec states that “Approximate literals support the use Java floating point literal syntax as well as SQL approximate numeric literal syntax.” This would suggest to me that {{double}} should be the default for JPQL as well.
( https://hibernate.atlassian.net/browse/HHH-16737#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16737#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100225- sha1:40c4da4 )
2 years, 10 months