mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 08:05:43 -06:00
Nested Folders: Use recursive query if the driver supports it (#58178)
* Nested Folders: Try first recursive query and fallback if it's not supported * Apply suggestion from code review Fix error msgID
This commit is contained in:
parent
ed64133943
commit
4d2be7a277
@ -2,14 +2,16 @@ package folderimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/VividCortex/mysqlerr"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"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"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
@ -183,9 +185,6 @@ func (ss *sqlStore) Get(ctx context.Context, q folder.GetFolderQuery) (*folder.F
|
||||
|
||||
func (ss *sqlStore) GetParents(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) {
|
||||
var folders []*folder.Folder
|
||||
if ss.db.GetDBType() == migrator.MySQL {
|
||||
return ss.getParentsMySQL(ctx, q)
|
||||
}
|
||||
|
||||
recQuery := `
|
||||
WITH RECURSIVE RecQry AS (
|
||||
@ -195,14 +194,23 @@ func (ss *sqlStore) GetParents(ctx context.Context, q folder.GetParentsQuery) ([
|
||||
SELECT * FROM RecQry;
|
||||
`
|
||||
|
||||
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
||||
if err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
||||
err := sess.SQL(recQuery, q.UID, q.OrgID).Find(&folders)
|
||||
if err != nil {
|
||||
return folder.ErrDatabaseError.Errorf("failed to get folder parents: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return util.Reverse(folders[1:]), err
|
||||
}); err != nil {
|
||||
var driverErr *mysql.MySQLError
|
||||
if errors.As(err, &driverErr) {
|
||||
if driverErr.Number == mysqlerr.ER_PARSE_ERROR {
|
||||
ss.log.Debug("recursive CTE subquery is not supported; it fallbacks to the iterative implementation")
|
||||
return ss.getParentsMySQL(ctx, q)
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return util.Reverse(folders[1:]), nil
|
||||
}
|
||||
|
||||
func (ss *sqlStore) GetChildren(ctx context.Context, q folder.GetTreeQuery) ([]*folder.Folder, error) {
|
||||
@ -228,20 +236,32 @@ func (ss *sqlStore) GetChildren(ctx context.Context, q folder.GetTreeQuery) ([]*
|
||||
return folders, err
|
||||
}
|
||||
|
||||
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=? AND org_id=>", uid, cmd.OrgID).Find(foldr)
|
||||
func (ss *sqlStore) getParentsMySQL(ctx context.Context, cmd folder.GetParentsQuery) (folders []*folder.Folder, err error) {
|
||||
err = ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
||||
uid := ""
|
||||
ok, err := sess.SQL("SELECT parent_uid FROM folder WHERE org_id=? AND uid=?", cmd.OrgID, cmd.UID).Get(&uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return folder.ErrFolderNotFound
|
||||
}
|
||||
for {
|
||||
f := &folder.Folder{}
|
||||
ok, err := sess.SQL("SELECT * FROM folder WHERE org_id=? AND uid=?", cmd.OrgID, uid).Get(f)
|
||||
if err != nil {
|
||||
return folder.ErrDatabaseError.Errorf("failed to get folder parents: %w", err)
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
folders = append(folders, f)
|
||||
uid = f.ParentUID
|
||||
if len(folders) > folder.MaxNestedFolderDepth {
|
||||
return folder.ErrFolderTooDeep
|
||||
}
|
||||
foldrs = append(foldrs, foldr)
|
||||
uid = foldr.ParentUID
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return foldrs, err
|
||||
return folders, err
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ var ErrMaximumDepthReached = errutil.NewBase(errutil.StatusBadRequest, "folder.m
|
||||
var ErrBadRequest = errutil.NewBase(errutil.StatusBadRequest, "folder.bad-request")
|
||||
var ErrDatabaseError = errutil.NewBase(errutil.StatusInternal, "folder.database-error")
|
||||
var ErrInternal = errutil.NewBase(errutil.StatusInternal, "folder.internal")
|
||||
var ErrFolderTooDeep = errutil.NewBase(errutil.StatusInternal, "folder.too-deep")
|
||||
|
||||
const (
|
||||
GeneralFolderUID = "general"
|
||||
|
Loading…
Reference in New Issue
Block a user