Skip to content

JPQL: attribute inside CASE WHEN fails in queries without an identification variable #2847

Description

@renatsaf

EclipseLink 5.0.1 (5.0.1.v202606291238) and master, H2 2.3.230, JDK 21.

An attribute referenced without an identification variable inside a CASE WHEN condition fails in a query that does not declare an identification variable (implicit this, as generated for Jakarta Data queries):

@Entity
public class Todo {
    @Id
    private Long id;
    private String title;
}
Query Result
SELECT this FROM Todo WHERE CASE WHEN id = 1 THEN 'x' ELSE 'y' END = 'x' JPQLException: 'id' cannot be resolved to a type
DELETE FROM Todo WHERE CASE WHEN id = 1 THEN 'x' ELSE 'y' END = 'x' JPQLException: 'id' cannot be resolved to a type
UPDATE Todo SET title = CASE WHEN id = 1 THEN 'x' ELSE 'y' END NullPointerException

The same queries work with this.id, or with an identification variable (FROM Todo t ... CASE WHEN t.id = 1). id outside CASE (WHERE id = 1) works as well.

UPDATE stack trace:

java.lang.NullPointerException: Cannot invoke "org.eclipse.persistence.descriptors.ClassDescriptor.getJavaClass()" because "descriptor" is null
    at org.eclipse.persistence.internal.jpa.jpql.ExpressionBuilderVisitor.visit(ExpressionBuilderVisitor.java:1081)
    at org.eclipse.persistence.jpa.jpql.parser.EntityTypeLiteral.accept(EntityTypeLiteral.java:42)
    at org.eclipse.persistence.internal.jpa.jpql.ExpressionBuilderVisitor$ComparisonExpressionVisitor.visit(ExpressionBuilderVisitor.java:2339)
    at org.eclipse.persistence.jpa.jpql.parser.AnonymousExpressionVisitor.visit(AnonymousExpressionVisitor.java:173)
    at org.eclipse.persistence.jpa.jpql.parser.EntityTypeLiteral.accept(EntityTypeLiteral.java:42)
    at org.eclipse.persistence.internal.jpa.jpql.ExpressionBuilderVisitor.visit(ExpressionBuilderVisitor.java:737)
    at org.eclipse.persistence.jpa.jpql.parser.ComparisonExpression.accept(ComparisonExpression.java:71)
    at org.eclipse.persistence.internal.jpa.jpql.ExpressionBuilderVisitor$WhenClauseExpressionVisitor.visit(ExpressionBuilderVisitor.java:2852)
    at org.eclipse.persistence.jpa.jpql.parser.WhenClause.accept(WhenClause.java:84)
    at org.eclipse.persistence.internal.jpa.jpql.ExpressionBuilderVisitor.visit(ExpressionBuilderVisitor.java:580)
    at org.eclipse.persistence.jpa.jpql.parser.CaseExpression.accept(CaseExpression.java:105)
    at org.eclipse.persistence.internal.jpa.jpql.ExpressionBuilderVisitor.buildExpression(ExpressionBuilderVisitor.java:285)

Inside the WHEN condition the bare id is parsed as an EntityTypeLiteral (an entity type name) rather than as an attribute, so it is not qualified with the implicit this: validation of the SELECT and DELETE queries reports it as an unknown type, and the UPDATE query passes validation and fails in ExpressionBuilderVisitor.visit(EntityTypeLiteral), where no descriptor exists for id.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions