Skip to content

Commit

Permalink
add space descendants data layer fn (harness#2511)
Browse files Browse the repository at this point in the history
* add space descendants data layer fn
  • Loading branch information
marko-gacesa authored and Harness committed Aug 14, 2024
1 parent 7e3253d commit d089d04
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 128 deletions.
2 changes: 1 addition & 1 deletion app/services/label/label_pullreq.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func (s *Service) ListPullReqLabels(
pullreqID int64,
filter *types.AssignableLabelFilter,
) (*types.ScopesLabels, int64, error) {
spaces, err := s.spaceStore.GetHierarchy(ctx, spaceID)
spaces, err := s.spaceStore.GetAncestors(ctx, spaceID)
if err != nil {
return nil, 0, fmt.Errorf("failed to get space hierarchy: %w", err)
}
Expand Down
12 changes: 8 additions & 4 deletions app/store/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,14 @@ type (
// GetAncestorIDs returns a list of all space IDs along the recursive path to the root space.
GetAncestorIDs(ctx context.Context, spaceID int64) ([]int64, error)

GetHierarchy(
ctx context.Context,
spaceID int64,
) ([]*types.Space, error)
// GetAncestors returns a list of all spaces along the recursive path to the root space.
GetAncestors(ctx context.Context, spaceID int64) ([]*types.Space, error)

// GetAncestorsData returns a list of space parent data for spaces that are ancestors of the space.
GetAncestorsData(ctx context.Context, spaceID int64) ([]types.SpaceParentData, error)

// GetDescendantsData returns a list of space parent data for spaces that are descendants of the space.
GetDescendantsData(ctx context.Context, spaceID int64) ([]types.SpaceParentData, error)

// Create creates a new space
Create(ctx context.Context, space *types.Space) error
Expand Down
122 changes: 43 additions & 79 deletions app/store/database/pullreq.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,45 +433,7 @@ func (s *PullReqStore) Count(ctx context.Context, opts *types.PullReqFilter) (in
}
stmt = stmt.From("pullreqs")

if len(opts.States) == 1 {
stmt = stmt.Where("pullreq_state = ?", opts.States[0])
} else if len(opts.States) > 1 {
stmt = stmt.Where(squirrel.Eq{"pullreq_state": opts.States})
}

if opts.SourceRepoID != 0 {
stmt = stmt.Where("pullreq_source_repo_id = ?", opts.SourceRepoID)
}

if opts.SourceBranch != "" {
stmt = stmt.Where("pullreq_source_branch = ?", opts.SourceBranch)
}

if opts.TargetRepoID != 0 {
stmt = stmt.Where("pullreq_target_repo_id = ?", opts.TargetRepoID)
}

if opts.TargetBranch != "" {
stmt = stmt.Where("pullreq_target_branch = ?", opts.TargetBranch)
}

if opts.Query != "" {
stmt = stmt.Where("LOWER(pullreq_title) LIKE ?", fmt.Sprintf("%%%s%%", strings.ToLower(opts.Query)))
}

if len(opts.CreatedBy) > 0 {
stmt = stmt.Where(squirrel.Eq{"pullreq_created_by": opts.CreatedBy})
}

if opts.CreatedLt > 0 {
stmt = stmt.Where("pullreq_created < ?", opts.CreatedLt)
}

if opts.CreatedGt > 0 {
stmt = stmt.Where("pullreq_created > ?", opts.CreatedGt)
}

setLabelKeyQuery(&stmt, opts)
s.applyFilter(&stmt, opts)

sql, args, err := stmt.ToSql()
if err != nil {
Expand Down Expand Up @@ -500,45 +462,7 @@ func (s *PullReqStore) List(ctx context.Context, opts *types.PullReqFilter) ([]*
}
stmt = stmt.From("pullreqs")

if len(opts.States) == 1 {
stmt = stmt.Where("pullreq_state = ?", opts.States[0])
} else if len(opts.States) > 1 {
stmt = stmt.Where(squirrel.Eq{"pullreq_state": opts.States})
}

if opts.SourceRepoID != 0 {
stmt = stmt.Where("pullreq_source_repo_id = ?", opts.SourceRepoID)
}

if opts.SourceBranch != "" {
stmt = stmt.Where("pullreq_source_branch = ?", opts.SourceBranch)
}

if opts.TargetRepoID != 0 {
stmt = stmt.Where("pullreq_target_repo_id = ?", opts.TargetRepoID)
}

if opts.TargetBranch != "" {
stmt = stmt.Where("pullreq_target_branch = ?", opts.TargetBranch)
}

if opts.Query != "" {
stmt = stmt.Where("LOWER(pullreq_title) LIKE ?", fmt.Sprintf("%%%s%%", strings.ToLower(opts.Query)))
}

if len(opts.CreatedBy) > 0 {
stmt = stmt.Where(squirrel.Eq{"pullreq_created_by": opts.CreatedBy})
}

if opts.CreatedLt > 0 {
stmt = stmt.Where("pullreq_created < ?", opts.CreatedLt)
}

if opts.CreatedGt > 0 {
stmt = stmt.Where("pullreq_created > ?", opts.CreatedGt)
}

setLabelKeyQuery(&stmt, opts)
s.applyFilter(&stmt, opts)

stmt = stmt.Limit(database.Limit(opts.Size))
stmt = stmt.Offset(database.Offset(opts.Page, opts.Size))
Expand Down Expand Up @@ -570,7 +494,47 @@ func (s *PullReqStore) List(ctx context.Context, opts *types.PullReqFilter) ([]*
return result, nil
}

func setLabelKeyQuery(stmt *squirrel.SelectBuilder, opts *types.PullReqFilter) {
func (*PullReqStore) applyFilter(stmt *squirrel.SelectBuilder, opts *types.PullReqFilter) {
if len(opts.States) == 1 {
*stmt = stmt.Where("pullreq_state = ?", opts.States[0])
} else if len(opts.States) > 1 {
*stmt = stmt.Where(squirrel.Eq{"pullreq_state": opts.States})
}

if opts.SourceRepoID != 0 {
*stmt = stmt.Where("pullreq_source_repo_id = ?", opts.SourceRepoID)
}

if opts.SourceBranch != "" {
*stmt = stmt.Where("pullreq_source_branch = ?", opts.SourceBranch)
}

if opts.TargetRepoID != 0 {
*stmt = stmt.Where("pullreq_target_repo_id = ?", opts.TargetRepoID)
}

if opts.TargetBranch != "" {
*stmt = stmt.Where("pullreq_target_branch = ?", opts.TargetBranch)
}

if opts.Query != "" {
*stmt = stmt.Where("LOWER(pullreq_title) LIKE ?", fmt.Sprintf("%%%s%%", strings.ToLower(opts.Query)))
}

if len(opts.CreatedBy) > 0 {
*stmt = stmt.Where(squirrel.Eq{"pullreq_created_by": opts.CreatedBy})
}

if opts.CreatedLt > 0 {
*stmt = stmt.Where("pullreq_created < ?", opts.CreatedLt)
}

if opts.CreatedGt > 0 {
*stmt = stmt.Where("pullreq_created > ?", opts.CreatedGt)
}

// labels

if len(opts.LabelID) == 0 && len(opts.ValueID) == 0 {
return
}
Expand Down
34 changes: 7 additions & 27 deletions app/store/database/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -562,19 +562,9 @@ func (s *RepoStore) countAll(
parentID int64,
filter *types.RepoFilter,
) (int64, error) {
query := `WITH RECURSIVE SpaceHierarchy AS (
SELECT space_id, space_parent_id
FROM spaces
WHERE space_id = $1
UNION
SELECT s.space_id, s.space_parent_id
FROM spaces s
JOIN SpaceHierarchy h ON s.space_parent_id = h.space_id
)
SELECT space_id
FROM SpaceHierarchy h1;`
query := spaceDescendantsQuery + `
SELECT space_descendant_id
FROM space_descendants`

db := dbtx.GetAccessor(ctx, s.db)

Expand Down Expand Up @@ -649,24 +639,14 @@ func (s *RepoStore) listAll(
parentID int64,
filter *types.RepoFilter,
) ([]*types.Repository, error) {
where := `WITH RECURSIVE SpaceHierarchy AS (
SELECT space_id, space_parent_id
FROM spaces
WHERE space_id = $1
UNION
SELECT s.space_id, s.space_parent_id
FROM spaces s
JOIN SpaceHierarchy h ON s.space_parent_id = h.space_id
)
SELECT space_id
FROM SpaceHierarchy h1;`
query := spaceDescendantsQuery + `
SELECT space_descendant_id
FROM space_descendants`

db := dbtx.GetAccessor(ctx, s.db)

var spaceIDs []int64
if err := db.SelectContext(ctx, &spaceIDs, where, parentID); err != nil {
if err := db.SelectContext(ctx, &spaceIDs, query, parentID); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "failed to retrieve spaces")
}

Expand Down
104 changes: 87 additions & 17 deletions app/store/database/space.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,26 +192,40 @@ func (s *SpaceStore) findByPathAndDeletedAt(
return s.find(ctx, spaceID, &deletedAt)
}

const spaceRecursiveQuery = `
WITH RECURSIVE SpaceHierarchy(space_hierarchy_id, space_hierarchy_parent_id) AS (
SELECT space_id, space_parent_id
const spaceAncestorsQuery = `
WITH RECURSIVE space_ancestors(space_ancestor_id, space_ancestor_uid, space_ancestor_parent_id) AS (
SELECT space_id, space_uid, space_parent_id
FROM spaces
WHERE space_id = $1
UNION
SELECT s.space_id, s.space_parent_id
FROM spaces s
JOIN SpaceHierarchy h ON s.space_id = h.space_hierarchy_parent_id
SELECT space_id, space_uid, space_parent_id
FROM spaces
JOIN space_ancestors ON space_id = space_ancestor_parent_id
)
`

const spaceDescendantsQuery = `
WITH RECURSIVE space_descendants(space_descendant_id, space_descendant_uid, space_descendant_parent_id) AS (
SELECT space_id, space_uid, space_parent_id
FROM spaces
WHERE space_id = $1
UNION
SELECT space_id, space_uid, space_parent_id
FROM spaces
JOIN space_descendants ON space_descendant_id = space_parent_id
)
`

// GetRootSpace returns a space where space_parent_id is NULL.
func (s *SpaceStore) GetRootSpace(ctx context.Context, spaceID int64) (*types.Space, error) {
query := spaceRecursiveQuery + `
SELECT space_hierarchy_id
FROM SpaceHierarchy
WHERE space_hierarchy_parent_id IS NULL;`
query := spaceAncestorsQuery + `
SELECT space_ancestor_id
FROM space_ancestors
WHERE space_ancestor_parent_id IS NULL`

db := dbtx.GetAccessor(ctx, s.db)

Expand All @@ -225,37 +239,93 @@ func (s *SpaceStore) GetRootSpace(ctx context.Context, spaceID int64) (*types.Sp

// GetAncestorIDs returns a list of all space IDs along the recursive path to the root space.
func (s *SpaceStore) GetAncestorIDs(ctx context.Context, spaceID int64) ([]int64, error) {
query := spaceRecursiveQuery + `
SELECT space_hierarchy_id FROM SpaceHierarchy`
query := spaceAncestorsQuery + `
SELECT space_ancestor_id FROM space_ancestors`

db := dbtx.GetAccessor(ctx, s.db)

var spaceIDs []int64
if err := db.SelectContext(ctx, &spaceIDs, query, spaceID); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "failed to get space hierarchy")
return nil, database.ProcessSQLErrorf(ctx, err, "failed to get space ancestors IDs")
}

return spaceIDs, nil
}

func (s *SpaceStore) GetHierarchy(
func (s *SpaceStore) GetAncestors(
ctx context.Context,
spaceID int64,
) ([]*types.Space, error) {
query := spaceRecursiveQuery + `
query := spaceAncestorsQuery + `
SELECT ` + spaceColumns + `
FROM spaces INNER JOIN SpaceHierarchy ON space_id = space_hierarchy_id`
FROM spaces INNER JOIN space_ancestors ON space_id = space_ancestor_id`

db := dbtx.GetAccessor(ctx, s.db)

var dst []*space
if err := db.SelectContext(ctx, &dst, query, spaceID); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing custom list query")
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing get space ancestors query")
}

return s.mapToSpaces(ctx, s.db, dst)
}

// GetAncestorsData returns a list of space parent data for spaces that are ancestors of the space.
func (s *SpaceStore) GetAncestorsData(ctx context.Context, spaceID int64) ([]types.SpaceParentData, error) {
query := spaceAncestorsQuery + `
SELECT space_ancestor_id, space_ancestor_uid, space_ancestor_parent_id FROM space_ancestors`

return s.readParentsData(ctx, query, spaceID)
}

// GetDescendantsData returns a list of space parent data for spaces that are descendants of the space.
func (s *SpaceStore) GetDescendantsData(ctx context.Context, spaceID int64) ([]types.SpaceParentData, error) {
query := spaceDescendantsQuery + `
SELECT space_descendant_id, space_descendant_uid, space_descendant_parent_id FROM space_descendants`

return s.readParentsData(ctx, query, spaceID)
}

func (s *SpaceStore) readParentsData(
ctx context.Context,
query string,
spaceID int64,
) ([]types.SpaceParentData, error) {
db := dbtx.GetAccessor(ctx, s.db)

rows, err := db.QueryContext(ctx, query, spaceID)
if err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "failed to run space parent data query")
}

defer func() { _ = rows.Close() }()

var result []types.SpaceParentData

for rows.Next() {
var id int64
var uid string
var parent null.Int

err = rows.Scan(&id, &uid, &parent)
if err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "failed to scan space parent data")
}

result = append(result, types.SpaceParentData{
ID: id,
Identifier: uid,
ParentID: parent.Int64,
})
}

if err := rows.Err(); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "failed to read space parent data")
}

return result, nil
}

// Create a new space.
func (s *SpaceStore) Create(ctx context.Context, space *types.Space) error {
if space == nil {
Expand Down
2 changes: 2 additions & 0 deletions types/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ type RepositoryGitInfo struct {
GitUID string
}

func (rgi *RepositoryGitInfo) GetGitUID() string { return rgi.GitUID }

type RepositoryPullReqSummary struct {
OpenCount int `json:"open_count"`
ClosedCount int `json:"closed_count"`
Expand Down
6 changes: 6 additions & 0 deletions types/space.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ type Space struct {
Deleted *int64 `json:"deleted,omitempty"`
}

type SpaceParentData struct {
ID int64 `json:"id"`
Identifier string `json:"identifier"`
ParentID int64 `json:"parent_id"`
}

// Stores spaces query parameters.
type SpaceFilter struct {
Page int `json:"page"`
Expand Down

0 comments on commit d089d04

Please sign in to comment.