eclipse-ee4j / eclipselink

Eclipselink project
https://eclipse.dev/eclipselink/
Other
192 stars 160 forks source link

JPQL SELECT not allowing entity attribute without optional entity identification variable #2182

Open Riva-Tholoor-Philip opened 3 days ago

Riva-Tholoor-Philip commented 3 days ago

EcilpseLink is rejecting JPQL SELECT clauses where the entity attribute omits the optional entity identification variable. For example for, SELECT hexadecimal FROM AsciiCharacter WHERE hexadecimal IS NOT NULL AND thisCharacter = ?1, EclipseLink raises an error: "The identification variable 'hexadecimal' is not defined in the FROM clause". It shouldn't need to be defined the from clause because this JPQL query is intentionally written without the entity identification variable to be consistent with JDQL.

Refer the logs:

Caused by: java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager: 
Exception Description: Problem compiling [SELECT hexadecimal FROM AsciiCharacter WHERE hexadecimal IS NOT NULL AND thisCharacter = ?1]. 
[7, 18] The identification variable 'hexadecimal' is not defined in the FROM clause.
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1848)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1869)
    at io.openliberty.data.internal.persistence.RepositoryImpl.invoke(RepositoryImpl.java:871)
    ... 40 more
Caused by: Exception [EclipseLink-0] (Eclipse Persistence Services - 5.0.0-B02.v202404111748): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Problem compiling [SELECT hexadecimal FROM AsciiCharacter WHERE hexadecimal IS NOT NULL AND thisCharacter = ?1]. 
[7, 18] The identification variable 'hexadecimal' is not defined in the FROM clause.
    at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildException(HermesParser.java:169)
    at org.eclipse.persistence.internal.jpa.jpql.HermesParser.validate(HermesParser.java:358)
    at org.eclipse.persistence.internal.jpa.jpql.HermesParser.populateQueryImp(HermesParser.java:292)
    at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildQuery(HermesParser.java:174)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:144)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:120)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:107)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:91)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1846)
lukasj commented 3 days ago

given that If the domain has exactly one named entity abstract schema type and no joins, then the named entity does not require an explicit identification variable, and its identification variable defaults to the implicit identification variable, this. one should use either SELECT hexadecimal FROM AsciiCharacter hexadecimal WHERE ... or SELECT this FROM AsciiCharacter WHERE ...

njr-11 commented 14 hours ago

given that If the domain has exactly one named entity abstract schema type and no joins, then the named entity does not require an explicit identification variable, and its identification variable defaults to the implicit identification variable, this. one should use either SELECT hexadecimal FROM AsciiCharacter hexadecimal WHERE ... or SELECT this FROM AsciiCharacter WHERE ...

The intent of this query is to retrieve a single entity attribute named hexadecimal, not the entire entity, so a query of the form, SELECT hexadecimal FROM ... is what we are aiming for here, not SELECT this FROM .... One problem that I see here is that the recommended query of SELECT hexadecimal FROM AsciiCharacter hexadecimal WHERE ... would not retrieve the single entity attribute named hexadecimal because the from clause FROM AsciiCharacter hexadecimal would turn hexadecimal into an entity identification variable for the AsciiCharacter entity. So, although that is a vaild JPQL query, it would end up retrieving the entire entity, which is not what is desired. That is why we instead wrote the query as:

SELECT hexadecimal FROM AsciiCharacter WHERE hexadecimal IS NOT NULL AND thisCharacter = ?1

which, if I correctly understand the statement, If the domain has exactly one named entity abstract schema type and no joins, then the named entity does not require an explicit identification variable, and its identification variable defaults to the implicit identification variable, this., ought to be equivalent to:

SELECT this.hexadecimal FROM AsciiCharacter WHERE this.hexadecimal IS NOT NULL AND this.thisCharacter = ?1

Also refer to the examples in Section 4.4.3 of the Jakarta Persistence 3.2 specification, which seem to show this same interpretation in stating that the query,

SELECT quantity
FROM Order
...

is equivalent to:

SELECT this.quantity
FROM Order
...

This is important to resolve because if it does not work this way, it would mean there is an incompatibility between JPQL and JDQL. JDQL is supposed to be a subset of JPQL such that every JDQL query can run as a valid JPQL query.