1
0

fix(project): check for project nesting cycles with a single recursive cte instead of a loop

This commit is contained in:
kolaente 2024-03-03 11:40:30 +01:00
parent 4bb09b69be
commit fe02f4da2c
No known key found for this signature in database
GPG Key ID: F40E70337AB24C9B

View File

@ -667,12 +667,34 @@ func checkProjectBeforeUpdateOrDelete(s *xorm.Session, project *Project) (err er
} }
} }
var parent *Project allProjects := make(map[int64]*Project)
parent, err = GetProjectSimpleByID(s, project.ParentProjectID) err = s.SQL(`WITH RECURSIVE all_projects AS (
SELECT
p.id,
p.parent_project_id
FROM
projects p
WHERE
p.id = ?
UNION ALL
SELECT
p.id,
p.parent_project_id
FROM
Projects p
INNER JOIN all_projects pc ON p.ID = pc.parent_project_id
)
SELECT
*
FROM
all_projects`, project.ParentProjectID).Find(&allProjects)
if err != nil { if err != nil {
return err return
} }
var parent *Project
parent = allProjects[project.ParentProjectID]
// Check if there's a cycle in the parent relation // Check if there's a cycle in the parent relation
parentsVisited := make(map[int64]bool) parentsVisited := make(map[int64]bool)
parentsVisited[project.ID] = true parentsVisited[project.ID] = true
@ -681,11 +703,7 @@ func checkProjectBeforeUpdateOrDelete(s *xorm.Session, project *Project) (err er
break break
} }
// FIXME: Can we do this with better performance? parent = allProjects[parent.ParentProjectID]
parent, err = GetProjectSimpleByID(s, parent.ParentProjectID)
if err != nil {
return err
}
if parentsVisited[parent.ID] { if parentsVisited[parent.ID] {
return &ErrProjectCannotHaveACyclicRelationship{ return &ErrProjectCannotHaveACyclicRelationship{