Skip to content

Query Parser Regression Bug in 3.3.5 #3661

@MartinHaeusler

Description

@MartinHaeusler

Spring Data 3.3.5 has a regression bug in its HQL query parser.

The following query:

    @Modifying
    @Query(
        value = """
        DELETE
        FROM
            MyEntity AS me
        WHERE
            me.deleted IS NOT NULL
        """
    )
    public void deleteAllSoftDeleted();

... creates an error during application startup:

org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract void com.example.demo.repository.MyEntityRepository.deleteAllSoftDeleted(); Reason: Cannot invoke "org.antlr.v4.runtime.ParserRuleContext.getParent()" because "ctx" is null
	at app//org.springframework.data.repository.query.QueryCreationException.create(QueryCreationException.java:101)
	at app//org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:119)
	at app//org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.mapMethodsToQuery(QueryExecutorMethodInterceptor.java:103)
	at app//org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lambda$new$0(QueryExecutorMethodInterceptor.java:92)
	at [email protected]/java.util.Optional.map(Optional.java:260)
	at app//org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.<init>(QueryExecutorMethodInterceptor.java:92)
	at app//org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:357)
	at app//org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:290)
	at app//org.springframework.data.util.Lazy.getNullable(Lazy.java:135)
	at app//org.springframework.data.util.Lazy.get(Lazy.java:113)
	at app//org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:296)
	at app//org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:132)
	at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853)
	at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802)
	... 52 more
Caused by: java.lang.NullPointerException: Cannot invoke "org.antlr.v4.runtime.ParserRuleContext.getParent()" because "ctx" is null
	at org.springframework.data.jpa.repository.query.HqlQueryTransformer.isSubquery(HqlQueryTransformer.java:105)
	at org.springframework.data.jpa.repository.query.HqlQueryTransformer.isSubquery(HqlQueryTransformer.java:105)
	at org.springframework.data.jpa.repository.query.HqlQueryTransformer.isSubquery(HqlQueryTransformer.java:105)
	at org.springframework.data.jpa.repository.query.HqlQueryTransformer.isSubquery(HqlQueryTransformer.java:105)
	at org.springframework.data.jpa.repository.query.HqlQueryTransformer.isSubquery(HqlQueryTransformer.java:105)
	at org.springframework.data.jpa.repository.query.HqlQueryTransformer.isSubquery(HqlQueryTransformer.java:105)
	at org.springframework.data.jpa.repository.query.HqlQueryTransformer.visitVariable(HqlQueryTransformer.java:362)
	at org.springframework.data.jpa.repository.query.HqlQueryRenderer.visitVariable(HqlQueryRenderer.java:1)
	at org.springframework.data.jpa.repository.query.HqlParser$VariableContext.accept(HqlParser.java:10200)
	at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visit(AbstractParseTreeVisitor.java:18)
	at org.springframework.data.jpa.repository.query.HqlQueryRenderer.visitTargetEntity(HqlQueryRenderer.java:481)
	at org.springframework.data.jpa.repository.query.HqlQueryRenderer.visitTargetEntity(HqlQueryRenderer.java:1)
	at org.springframework.data.jpa.repository.query.HqlParser$TargetEntityContext.accept(HqlParser.java:2018)
	at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visit(AbstractParseTreeVisitor.java:18)
	at org.springframework.data.jpa.repository.query.HqlQueryRenderer.visitDeleteStatement(HqlQueryRenderer.java:526)
	at org.springframework.data.jpa.repository.query.HqlQueryRenderer.visitDeleteStatement(HqlQueryRenderer.java:1)
	at org.springframework.data.jpa.repository.query.HqlParser$DeleteStatementContext.accept(HqlParser.java:2198)
	at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visit(AbstractParseTreeVisitor.java:18)
	at org.springframework.data.jpa.repository.query.HqlQueryRenderer.visitQl_statement(HqlQueryRenderer.java:46)
	at org.springframework.data.jpa.repository.query.HqlQueryRenderer.visitQl_statement(HqlQueryRenderer.java:1)
	at org.springframework.data.jpa.repository.query.HqlParser$Ql_statementContext.accept(HqlParser.java:303)
	at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visit(AbstractParseTreeVisitor.java:18)
	at org.springframework.data.jpa.repository.query.HqlQueryRenderer.visitStart(HqlQueryRenderer.java:35)
	at org.springframework.data.jpa.repository.query.HqlQueryRenderer.visitStart(HqlQueryRenderer.java:1)
	at org.springframework.data.jpa.repository.query.HqlParser$StartContext.accept(HqlParser.java:247)
	at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visit(AbstractParseTreeVisitor.java:18)
	at org.springframework.data.jpa.repository.query.HqlQueryParser.doFindAlias(HqlQueryParser.java:101)
	at org.springframework.data.jpa.repository.query.JpaQueryParserSupport.findAlias(JpaQueryParserSupport.java:96)
	at org.springframework.data.jpa.repository.query.JpaQueryEnhancer.detectAlias(JpaQueryEnhancer.java:124)
	at org.springframework.data.jpa.repository.query.StringQuery.<init>(StringQuery.java:90)
	at org.springframework.data.jpa.repository.query.DeclaredQuery.of(DeclaredQuery.java:40)
	at org.springframework.data.jpa.repository.query.JpaQueryMethod.assertParameterNamesInAnnotatedQuery(JpaQueryMethod.java:168)
	at org.springframework.data.jpa.repository.query.JpaQueryMethod.<init>(JpaQueryMethod.java:149)
	at org.springframework.data.jpa.repository.query.DefaultJpaQueryMethodFactory.build(DefaultJpaQueryMethodFactory.java:44)
	at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:94)
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:115)
	... 64 more

I had a quick look at the code. At first glance to me it seems that HqlQueryTransformer.isSubquery is either missing a case in its instanceof cascade, or should not have been called in the first place.

The same code works fine in 3.3.4.

A minimal reproducer is available here: https://github.com/MartinHaeusler/springDataParseErrorReproducer

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions