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

Support of CTE with Pageable #41076

Closed
bountin opened this issue Jun 11, 2024 · 1 comment
Closed

Support of CTE with Pageable #41076

bountin opened this issue Jun 11, 2024 · 1 comment
Labels
for: external-project For an external project and not something we can fix

Comments

@bountin
Copy link

bountin commented Jun 11, 2024

I've eagerly tried the CTE support with Hibernate but was quickly limited by Spring Data JPA's support of it. Here is a (tbc) repository illustrating all of the three points below. There are workarounds for the issues with Pageable but they involve processing the client's PageRequest manually, and a bunch of query duplications.

Two of the following three issues persist in 3.3.0, one was fixed (accidentally?) after 3.2.5. All of the queries below are annotated on a repository method with @Query.

Simple CTE with Pageable

WITH entities AS (
    SELECT e.id as id, e.number as number
    FROM TestEntity e
)
SELECT new com.example.demo.Result('X', c.id, c.number)
FROM entities c

This HQL snippet (with a Pageable sort and paging) failed up to 3.2.5 but was fixed in 3.2.6 and 3.3.0. Unfortunately, I could not find any related ticket or release note entry.

Because it is already fixed, I won't write much more here :)

Automatic countQuery with CTE

If one leaves the countQuery parameter empty, so that Spring Data generates one for a query with a CTE, it will fail with the following stack trace:

Caused by: org.hibernate.query.SemanticException: Select item at position 1 in select list has no alias (aliases are required in CTEs and in subqueries occurring in from clause)
	at org.hibernate.query.derived.AnonymousTupleType.<init>(AnonymousTupleType.java:62)
	at org.hibernate.query.sqm.tree.cte.SqmCteTable.<init>(SqmCteTable.java:40)
	at org.hibernate.query.sqm.tree.cte.SqmCteTable.createStatementTable(SqmCteTable.java:65)
	at org.hibernate.query.sqm.tree.cte.SqmCteStatement.<init>(SqmCteStatement.java:64)
	at org.hibernate.query.sqm.tree.select.AbstractSqmSelectQuery.withInternal(AbstractSqmSelectQuery.java:175)
	at org.hibernate.query.sqm.tree.select.AbstractSqmSelectQuery.with(AbstractSqmSelectQuery.java:136)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitCte(SemanticQueryBuilder.java:885)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitWithClause(SemanticQueryBuilder.java:757)
	at org.hibernate.grammars.hql.HqlParser$WithClauseContext.accept(HqlParser.java:1405)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSimpleQueryGroup(SemanticQueryBuilder.java:1018)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSimpleQueryGroup(SemanticQueryBuilder.java:275)
	at org.hibernate.grammars.hql.HqlParser$SimpleQueryGroupContext.accept(HqlParser.java:2003)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSelectStatement(SemanticQueryBuilder.java:490)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitStatement(SemanticQueryBuilder.java:449)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.buildSemanticModel(SemanticQueryBuilder.java:322)
	at org.hibernate.query.hql.internal.StandardHqlTranslator.translate(StandardHqlTranslator.java:71)
	at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.createHqlInterpretation(QueryInterpretationCacheStandardImpl.java:145)
	at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.resolveHqlInterpretation(QueryInterpretationCacheStandardImpl.java:132)
	at org.hibernate.internal.AbstractSharedSessionContract.interpretHql(AbstractSharedSessionContract.java:802)
	at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:852)

Essentially, Spring Data generates the following HQL that of course is not a correct count query:

WITH entities AS(
    SELECT count(e) FROM TestEntity e
) SELECT count(e) FROM entities c

CTE and UNION ALL

A query as follows will again fail with a sorting/paging Pageable parameter:

WITH entities AS (
    SELECT e.id as id, e.number as number FROM TestEntity e
),
combined AS (
    SELECT 'A' as source, a.id as id, a.number as number
    FROM entities as a

    UNION ALL

    SELECT 'B' as source, b.id as id, b.number as number
    FROM entities as b
)
SELECT new com.example.demo.Result(c.source, c.id, c.number)
FROM combined as c

This time, Spring Data fails to generate correct HQL. It again pushes the order into the UNION CTE - which is superfluous - and misses to add a space after the ASC key word as seen in the following part of the generated query: ... order by number ascUNION ALL SELECT 'B' as source, ...

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jun 11, 2024
@bountin
Copy link
Author

bountin commented Jun 11, 2024

Ah, nevermind! (and sorry!)
This was actually supposed to go here: spring-projects/spring-data-jpa#3504

@bountin bountin closed this as not planned Won't fix, can't repro, duplicate, stale Jun 11, 2024
@scottfrederick scottfrederick added for: external-project For an external project and not something we can fix and removed status: waiting-for-triage An issue we've not yet triaged labels Jun 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix
Projects
None yet
Development

No branches or pull requests

3 participants