fix(project): check for project nesting cycles with a single recursive cte instead of a loop
This commit is contained in:
parent
4bb09b69be
commit
fe02f4da2c
@ -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{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user