Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

id(this) not accepted in SELECT and WHERE clauses #2189

Open
anija-anil opened this issue Jul 2, 2024 · 4 comments
Open

id(this) not accepted in SELECT and WHERE clauses #2189

anija-anil opened this issue Jul 2, 2024 · 4 comments

Comments

@anija-anil
Copy link
Contributor

EclipseLink is not accepting the id(this) operation, which is new in Jakarta Persistence 3.2, when it is placed within a JPQL SELECT or WHERE clause. (It's possible other clauses might not work either -- this query only tried SELECT and WHERE),

SELECT ID(THIS) FROM Prime o WHERE (o.name = :numberName OR :numeral=o.romanNumeral OR o.hex =:hex OR ID(THIS)=:num) ORDER BY o.numberId

Here is the error:

Caused by: java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager: 
Exception Description: Problem compiling [SELECT ID(THIS) FROM Prime o WHERE (o.name = :numberName OR :numeral=o.romanNumeral OR o.hex =:hex OR ID(THIS)=:num) ORDER BY o.numberId]. 
[10, 14] The identification variable 'THIS' is not defined in the FROM clause.
[108, 112] The identification variable 'THIS' 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)
	... 42 more
Caused by: Exception [EclipseLink-0] (Eclipse Persistence Services - 5.0.0-B02.v202404111748): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Problem compiling [SELECT ID(THIS) FROM Prime o WHERE (o.name = :numberName OR :numeral=o.romanNumeral OR o.hex =:hex OR ID(THIS)=:num) ORDER BY o.numberId]. 
[10, 14] The identification variable 'THIS' is not defined in the FROM clause.
[108, 112] The identification variable 'THIS' 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)
	... 44 more
@Riva-Tholoor-Philip
Copy link
Contributor

I could recreate the issue.

Below is the Prime entity we have by referencing the entity present in Jakarta Data.

@Entity
public class Prime {
   public String binaryDigits;
   public boolean even;
   public String hex;
   public String name;

    @Id
    public long numberId;
    public String romanNumeral;
    public ArrayList<String> romanNumeralSymbols;
    public int sumOfBits;

    public static Prime of(long number, String romanNumeral, String name) {
        Prime inst = new Prime();
        inst.binaryDigits = Long.toBinaryString(number);
        inst.even = number % 2 == 0;
        inst.hex = Long.toHexString(number);
        inst.name = name;
        inst.romanNumeral = romanNumeral;
        inst.numberId = number;
        inst.sumOfBits = Long.bitCount(number);
        if (romanNumeral != null) {
            inst.romanNumeralSymbols = new ArrayList<>(romanNumeral.length());
            for (int i = 0; i < romanNumeral.length(); i++)
                inst.romanNumeralSymbols.add(romanNumeral.substring(i, i + 1));
        }

        return inst;
    }
}

Here is the code where we executed the JPQL query:

public void testOLGH28925() throws Exception {
        Prime two = Prime.of(2, "II", "two");
        Prime three = Prime.of(3, "III", "three");
        Prime five = Prime.of(5, "V", "five");
        Prime seven = Prime.of(7, "VII", "seven");

        List<Prime> primes;

        tx.begin();
        em.persist(two);
        em.persist(three);
        em.persist(five);
        em.persist(seven);
        tx.commit();

        tx.begin();
        try {
            primes = em.createQuery("SELECT ID(THIS) FROM Prime o WHERE (o.name = :numberName OR :numeral=o.romanNumeral OR o.hex =:hex OR ID(THIS)=:num) ORDER BY o.numberId",
                                    Prime.class)
                            .setParameter("numberName", "two")
                            .setParameter("numeral", "III")
                            .setParameter("hex", "5")
                            .setParameter("num", 7)
                            .getResultList();
            tx.commit();
        } catch (Exception e) {
            tx.rollback();

            throw e;
        }

This resulted in the following exception stack, which is the same as described in the issue:

Caused by: Exception [EclipseLink-0] (Eclipse Persistence Services - 5.0.0-B02.v202404111748): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Problem compiling [SELECT ID(THIS) FROM Prime o WHERE (o.name = :numberName OR :numeral=o.romanNumeral OR o.hex =:hex OR ID(THIS)=:num) ORDER BY o.numberId].
[10, 14] The identification variable 'THIS' is not defined in the FROM clause.
[108, 112] The identification variable 'THIS' 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)

at componenttest.topology.utils.FATServletClient.assertTestResponse(FATServletClient.java:106)
at componenttest.topology.utils.FATServletClient.runTest(FATServletClient.java:91)
at componenttest.custom.junit.runner.SyntheticServletTest.invokeExplosively(SyntheticServletTest.java:49)
at componenttest.custom.junit.runner.FATRunner$1.evaluate(FATRunner.java:204)
at componenttest.custom.junit.runner.FATRunner$2.evaluate(FATRunner.java:364)
at componenttest.custom.junit.runner.FATRunner.run(FATRunner.java:178)
at org.testcontainers.containers.FailureDetectingExternalResource$1.evaluate(FailureDetectingExternalResource.java:29)
at componenttest.rules.repeater.RepeatTests$CompositeRepeatTestActionStatement.evaluate(RepeatTests.java:145)

@rfelcman
Copy link
Contributor

rfelcman commented Oct 7, 2024

Sorry but mentioned query SELECT ID(THIS) FROM Prime o WHERE (o.name = :numberName OR :numeral=o.romanNumeral OR o.hex =:hex OR ID(THIS)=:num) ORDER BY o.numberId is incorrect. There is explicit entity alias ...FROM Prime o..... This one should not be used as there is mix of o and this. JPQL parser expect explicitly defined Prime o
Correct queries are:

  • explicit o: SELECT ID(o) FROM Prime o WHERE (o.name = :numberName OR :numeral=o.romanNumeral OR o.hex =:hex OR ID(o)=:num) ORDER BY o.numberId
  • explicit this: SELECT ID(THIS) FROM Prime this WHERE (thid.name = :numberName OR :numeral=this.romanNumeral OR thiss.hex =:hex OR ID(THIS)=:num) ORDER BY this.numberId
  • implicit this: SELECT ID(THIS) FROM Prime WHERE (thid.name = :numberName OR :numeral=this.romanNumeral OR thiss.hex =:hex OR ID(THIS)=:num) ORDER BY this.numberId

@anija-anil
Copy link
Contributor Author

@rfelcman
You mentioned that the query is incorrect due to the explicit entity alias “FROM Prime o” and the mixing of o with `THIS.” However, upon reviewing the Jakarta Persistence 3.2 Specification, we were unable to find a definitive statement prohibiting the use of ID(THIS) in conjunction with entity identifier variables.

Could you please provide clarification on whether this query is indeed invalid?

@rfelcman
Copy link
Contributor

rfelcman commented Oct 9, 2024

@rfelcman You mentioned that the query is incorrect due to the explicit entity alias “FROM Prime o” and the mixing of o with `THIS.” However, upon reviewing the Jakarta Persistence 3.2 Specification, we were unable to find a definitive statement prohibiting the use of ID(THIS) in conjunction with entity identifier variables.

Could you please provide clarification on whether this query is indeed invalid?

Do You mean that two aliases identification_variable for one entity should be valid?
What about 4.4. The FROM Clause and Navigational Declarations from_clause ::= FROM {this_implicit_variable | identification_variable_declarations}.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants