2022-10-26 10:52:01 -05:00
|
|
|
package folderimpl
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-10-28 13:07:25 -05:00
|
|
|
"encoding/binary"
|
2022-10-26 10:52:01 -05:00
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/infra/db"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
|
|
"github.com/grafana/grafana/pkg/services/folder"
|
2022-10-28 13:07:25 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
2022-10-26 10:52:01 -05:00
|
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
|
|
)
|
|
|
|
|
|
|
|
type sqlStore struct {
|
|
|
|
db db.DB
|
|
|
|
log log.Logger
|
|
|
|
cfg *setting.Cfg
|
|
|
|
fm featuremgmt.FeatureManager
|
|
|
|
}
|
|
|
|
|
|
|
|
// sqlStore implements the store interface.
|
|
|
|
var _ store = (*sqlStore)(nil)
|
|
|
|
|
|
|
|
func ProvideStore(db db.DB, cfg *setting.Cfg, features featuremgmt.FeatureManager) *sqlStore {
|
|
|
|
return &sqlStore{db: db, log: log.New("folder-store"), cfg: cfg, fm: features}
|
|
|
|
}
|
|
|
|
|
2022-10-28 08:35:49 -05:00
|
|
|
func (ss *sqlStore) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (*folder.Folder, error) {
|
2022-10-28 13:07:25 -05:00
|
|
|
foldr := &folder.Folder{
|
|
|
|
OrgID: cmd.OrgID,
|
|
|
|
UID: cmd.UID,
|
|
|
|
ParentUID: cmd.ParentUID,
|
|
|
|
Title: cmd.Title,
|
|
|
|
Description: cmd.Description,
|
|
|
|
}
|
|
|
|
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
|
|
|
folderID, err := sess.Insert(foldr)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
foldr.ID = folderID
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return foldr, err
|
2022-10-26 10:52:01 -05:00
|
|
|
}
|
|
|
|
|
2022-10-28 08:35:49 -05:00
|
|
|
func (ss *sqlStore) Delete(ctx context.Context, uid string, orgID int64) error {
|
|
|
|
return ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
|
|
|
_, err := sess.Exec("DELETE FROM folder WHERE folder_uid=? AND org_id=?", uid, orgID)
|
|
|
|
return err
|
|
|
|
})
|
2022-10-26 10:52:01 -05:00
|
|
|
}
|
|
|
|
|
2022-10-28 08:35:49 -05:00
|
|
|
func (ss *sqlStore) Update(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) {
|
|
|
|
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
|
|
|
_, err := sess.ID(cmd.Folder.ID).AllCols().Update(cmd.Folder)
|
|
|
|
return err
|
|
|
|
})
|
2022-10-26 10:52:01 -05:00
|
|
|
|
2022-10-28 08:35:49 -05:00
|
|
|
return cmd.Folder, err
|
2022-10-26 10:52:01 -05:00
|
|
|
}
|
|
|
|
|
2022-10-28 08:35:49 -05:00
|
|
|
func (ss *sqlStore) Get(ctx context.Context, cmd *folder.GetFolderQuery) (*folder.Folder, error) {
|
|
|
|
var foldr *folder.Folder
|
|
|
|
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
|
|
|
exists, err := sess.Where("uid=? OR id=? OR title=?", cmd.UID, cmd.ID, cmd.Title).Get(foldr)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if !exists {
|
|
|
|
return folder.ErrFolderNotFound.Errorf("folder not found")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return foldr, err
|
2022-10-26 10:52:01 -05:00
|
|
|
}
|
|
|
|
|
2022-10-28 08:35:49 -05:00
|
|
|
func (ss *sqlStore) GetParents(ctx context.Context, cmd *folder.GetParentsQuery) ([]*folder.Folder, error) {
|
2022-10-28 13:07:25 -05:00
|
|
|
var folders []*folder.Folder
|
|
|
|
if ss.db.GetDBType() == migrator.MySQL {
|
|
|
|
return ss.getParentsMySQL(ctx, cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
recQuery :=
|
|
|
|
`WITH RecQry AS (
|
|
|
|
SELECT *
|
|
|
|
FROM folder
|
|
|
|
UNION ALL
|
|
|
|
SELECT f.*
|
|
|
|
FROM folder f INNER JOIN RecQry r
|
|
|
|
ON f.parent_uid = r.uid
|
|
|
|
)
|
|
|
|
SELECT *
|
|
|
|
FROM RecQry`
|
|
|
|
|
|
|
|
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
|
|
|
res, err := sess.Query(recQuery)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, row := range res {
|
|
|
|
folders = append(folders, &folder.Folder{
|
|
|
|
ID: int64(binary.BigEndian.Uint64(row["id"])),
|
|
|
|
OrgID: int64(binary.BigEndian.Uint64(row["org_id"])),
|
|
|
|
UID: string(row["uid"]),
|
|
|
|
ParentUID: string(row["parent_uid"]),
|
|
|
|
Title: string(row["title"]),
|
|
|
|
Description: string(row["description"]),
|
|
|
|
// CreatedBy: int64(binary.BigEndian.Uint64(row["created_by"])),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return nil, err
|
2022-10-26 10:52:01 -05:00
|
|
|
}
|
|
|
|
|
2022-10-28 08:35:49 -05:00
|
|
|
func (ss *sqlStore) GetChildren(ctx context.Context, cmd *folder.GetTreeQuery) ([]*folder.Folder, error) {
|
|
|
|
var folders []*folder.Folder
|
2022-10-28 13:07:25 -05:00
|
|
|
|
2022-10-28 08:35:49 -05:00
|
|
|
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
|
|
|
err := sess.Where("parent_uid=? AND org_id=?", cmd.UID, cmd.OrgID).Find(folders)
|
|
|
|
return err
|
|
|
|
})
|
|
|
|
return folders, err
|
2022-10-26 10:52:01 -05:00
|
|
|
}
|
2022-10-28 13:07:25 -05:00
|
|
|
|
|
|
|
func (ss *sqlStore) getParentsMySQL(ctx context.Context, cmd *folder.GetParentsQuery) ([]*folder.Folder, error) {
|
|
|
|
var foldrs []*folder.Folder
|
|
|
|
var foldr *folder.Folder
|
|
|
|
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
|
|
|
uid := cmd.UID
|
|
|
|
for uid != folder.GeneralFolderUID && len(foldrs) < 8 {
|
|
|
|
err := sess.Where("uid=?", uid).Find(foldr)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
foldrs = append(foldrs, foldr)
|
|
|
|
uid = foldr.ParentUID
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return foldrs, err
|
|
|
|
}
|