fix(project): check for project nesting cycles with a single recursive cte instead of a loop
continuous-integration/drone/push Build is failing Details

This commit is contained in:
kolaente 2024-03-03 11:40:30 +01:00
parent 4bb09b69be
commit fe02f4da2c
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
1 changed files with 26 additions and 8 deletions

View File

@ -667,12 +667,34 @@ func checkProjectBeforeUpdateOrDelete(s *xorm.Session, project *Project) (err er
}
}
var parent *Project
parent, err = GetProjectSimpleByID(s, project.ParentProjectID)
allProjects := make(map[int64]*Project)
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 {
return err
return
}
var parent *Project
parent = allProjects[project.ParentProjectID]
// Check if there's a cycle in the parent relation
parentsVisited := make(map[int64]bool)
parentsVisited[project.ID] = true
@ -681,11 +703,7 @@ func checkProjectBeforeUpdateOrDelete(s *xorm.Session, project *Project) (err er
break
}
// FIXME: Can we do this with better performance?
parent, err = GetProjectSimpleByID(s, parent.ParentProjectID)
if err != nil {
return err
}
parent = allProjects[parent.ParentProjectID]
if parentsVisited[parent.ID] {
return &ErrProjectCannotHaveACyclicRelationship{