[JIRA] (HHH-16465) CTE query cycle attribute evaluated incorrectly on MSSQL
by MK (JIRA)
MK ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=70121%3... ) *created* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiMmI1MDIwZmY3... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16465?atlOrigin=eyJpIjoiMmI1MD... ) HHH-16465 ( https://hibernate.atlassian.net/browse/HHH-16465?atlOrigin=eyJpIjoiMmI1MD... ) CTE query cycle attribute evaluated incorrectly on MSSQL ( https://hibernate.atlassian.net/browse/HHH-16465?atlOrigin=eyJpIjoiMmI1MD... )
Issue Type: Bug Affects Versions: 6.2.0 Assignee: Unassigned Components: hibernate-core Created: 13/Apr/2023 06:03 AM Environment: Microsoft SQL Server Priority: Major Reporter: MK ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=70121%3... )
We noticed that our recursive CTE query returns incomplete results because it does not return the whole hierarchy.
It seems that the SQL generated for recognizing circular references is incorrect for MSSQL.
Given the following entities:
@Entity
@Table(name = "GROUP_TABLE" )
public class Group {
@Id
private Long id;
@Column(name = "NAME" , nullable = false )
private String name;
@Entity
@Table(name = "GROUP_TREE_TABLE" )
public class GroupTree {
@Id
private Long id;
@ManyToOne(optional = false )
@JoinColumn(name = "PARENT_ID" , nullable = false )
private Group parent;
@ManyToOne(optional = false )
@JoinColumn(name = "CHILD_ID" , nullable = false )
private Group child;
And the following CTE query:
WITH AllParents AS (
SELECT c child, p parent, gt.id groupTreeId
FROM GroupTree gt
INNER JOIN gt.parent p
INNER JOIN gt.child c
WHERE c = : start
UNION ALL
SELECT c2 child, p2 parent, gt2.id groupTreeId
FROM AllParents cte
JOIN GroupTree gt2 ON cte.parent = gt2.child
INNER JOIN gt2.parent p2
INNER JOIN gt2.child c2
) cycle groupTreeId set cycleMark
SELECT ap.child, ap.parent, ap.groupTreeId, ap.cycleMark FROM AllParents ap
The following SQL is generated:
with AllParents (child_id,parent_id,groupTreeId,cycleMark, path ) as ( select
g1_0.CHILD_ID,g1_0.PARENT_ID,g1_0.id,0,( coalesce ( cast (g1_0.id as varchar ( max )), char (0))+ char (0)+ char (0))
from
GROUP_TREE_TABLE g1_0
join
GROUP_TABLE c1_0
on c1_0.id=g1_0.CHILD_ID
where
c1_0.id=?
union
all select
g2_0.CHILD_ID,g2_0.PARENT_ID,g2_0.id, case
when cte1_0. path like ( '%' + coalesce ( cast (g2_0.id as varchar ( max )), char (0))+ char (0)+ char (0)+ '%' ) then 1
else 0
end ,(cte1_0. path + coalesce ( cast (g2_0.id as varchar ( max )), char (0))+ char (0)+ char (0))
from
AllParents cte1_0
join
GROUP_TREE_TABLE g2_0
on cte1_0.parent_id=g2_0.CHILD_ID
where
cte1_0.cycleMark=0) select
child1_0.id,
child1_0. NAME ,
parent2_0.id,
parent2_0. NAME ,
ap1_0.groupTreeId,
ap1_0.cycleMark
from
AllParents ap1_0
join
GROUP_TABLE child1_0
on ap1_0.child_id=child1_0.id
join
GROUP_TABLE parent2_0
on ap1_0.parent_id=parent2_0.id
Given the following hierarchy:
Group 4
\ (GroupTree id=2)
Group 3
\ (GroupTree id=1)
Group 2
\ (GroupTree id=11)
Group 1
When reaching (GroupTree id=1) the path looks like this: 11 [char(0)] [char(0)]. This results in LIKE %1 [char(0)] [char(0)] % being true, which is wrong, because 1 is not in the path yet, only 11.
A possible fix would be to add the separator to the beginning of the path as well and check for % [char(0)] [char(0)] 1 [char(0)] [char(0)] %.
I added a reproducer test case which runs fine on H2, but fails on MSSQL.
( https://hibernate.atlassian.net/browse/HHH-16465#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16465#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100221- sha1:5609d8c )
3 years