| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | package folderimpl | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2022-11-09 03:53:05 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 	"strings" | 
					
						
							|  |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-09 03:53:05 +08:00
										 |  |  | 	"github.com/VividCortex/mysqlerr" | 
					
						
							|  |  |  | 	"github.com/go-sql-driver/mysql" | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/db" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/infra/log" | 
					
						
							| 
									
										
										
										
											2022-12-01 00:12:56 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/slugify" | 
					
						
							| 
									
										
										
										
											2022-11-22 20:04:09 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/models" | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/featuremgmt" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/folder" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/setting" | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/util" | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type sqlStore struct { | 
					
						
							|  |  |  | 	db  db.DB | 
					
						
							|  |  |  | 	log log.Logger | 
					
						
							|  |  |  | 	cfg *setting.Cfg | 
					
						
							| 
									
										
										
										
											2022-11-08 21:59:55 +08:00
										 |  |  | 	fm  featuremgmt.FeatureToggles | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // sqlStore implements the store interface.
 | 
					
						
							|  |  |  | var _ store = (*sqlStore)(nil) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-08 21:59:55 +08:00
										 |  |  | func ProvideStore(db db.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles) *sqlStore { | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | 	return &sqlStore{db: db, log: log.New("folder-store"), cfg: cfg, fm: features} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | func (ss *sqlStore) Create(ctx context.Context, cmd folder.CreateFolderCommand) (*folder.Folder, error) { | 
					
						
							|  |  |  | 	if cmd.UID == "" { | 
					
						
							|  |  |  | 		return nil, folder.ErrBadRequest.Errorf("missing UID") | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var foldr *folder.Folder | 
					
						
							| 
									
										
										
										
											2022-11-10 17:41:03 +08:00
										 |  |  | 	/* | 
					
						
							|  |  |  | 		version := 1 | 
					
						
							| 
									
										
										
										
											2022-11-23 22:44:45 +08:00
										 |  |  | 		updatedBy := cmd.SignedInUser.UserID | 
					
						
							|  |  |  | 		createdBy := cmd.SignedInUser.UserID | 
					
						
							| 
									
										
										
										
											2022-11-10 17:41:03 +08:00
										 |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2022-11-28 23:48:44 +08:00
										 |  |  | 	var lastInsertedID int64 | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 	err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { | 
					
						
							| 
									
										
										
										
											2022-11-28 23:48:44 +08:00
										 |  |  | 		var sql string | 
					
						
							|  |  |  | 		var args []interface{} | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		if cmd.ParentUID == "" { | 
					
						
							| 
									
										
										
										
											2022-11-28 23:48:44 +08:00
										 |  |  | 			sql = "INSERT INTO folder(org_id, uid, title, description, created, updated) VALUES(?, ?, ?, ?, ?, ?)" | 
					
						
							|  |  |  | 			args = []interface{}{cmd.OrgID, cmd.UID, cmd.Title, cmd.Description, time.Now(), time.Now()} | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			if cmd.ParentUID != folder.GeneralFolderUID { | 
					
						
							|  |  |  | 				if _, err := ss.Get(ctx, folder.GetFolderQuery{ | 
					
						
							|  |  |  | 					UID:   &cmd.ParentUID, | 
					
						
							|  |  |  | 					OrgID: cmd.OrgID, | 
					
						
							|  |  |  | 				}); err != nil { | 
					
						
							| 
									
										
										
										
											2022-11-10 17:41:03 +08:00
										 |  |  | 					return folder.ErrFolderNotFound.Errorf("parent folder does not exist") | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-11-28 23:48:44 +08:00
										 |  |  | 			sql = "INSERT INTO folder(org_id, uid, parent_uid, title, description, created, updated) VALUES(?, ?, ?, ?, ?, ?, ?)" | 
					
						
							|  |  |  | 			args = []interface{}{cmd.OrgID, cmd.UID, cmd.ParentUID, cmd.Title, cmd.Description, time.Now(), time.Now()} | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-11-28 23:48:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		var err error | 
					
						
							|  |  |  | 		lastInsertedID, err = sess.WithReturningID(ss.db.GetDialect().DriverName(), sql, args) | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2022-11-28 23:48:44 +08:00
										 |  |  | 			return err | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		foldr, err = ss.Get(ctx, folder.GetFolderQuery{ | 
					
						
							| 
									
										
										
										
											2022-11-28 23:48:44 +08:00
										 |  |  | 			ID: &lastInsertedID, | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	return foldr, err | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | func (ss *sqlStore) Delete(ctx context.Context, uid string, orgID int64) error { | 
					
						
							|  |  |  | 	return ss.db.WithDbSession(ctx, func(sess *db.Session) error { | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		_, err := sess.Exec("DELETE FROM folder WHERE uid=? AND org_id=?", uid, orgID) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return folder.ErrDatabaseError.Errorf("failed to delete folder: %w", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | func (ss *sqlStore) Update(ctx context.Context, cmd folder.UpdateFolderCommand) (*folder.Folder, error) { | 
					
						
							|  |  |  | 	if cmd.Folder == nil { | 
					
						
							|  |  |  | 		return nil, folder.ErrBadRequest.Errorf("invalid update command: missing folder") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmd.Folder.Updated = time.Now() | 
					
						
							| 
									
										
										
										
											2022-11-04 17:04:24 +08:00
										 |  |  | 	existingUID := cmd.Folder.UID | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | 	err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { | 
					
						
							| 
									
										
										
										
											2022-11-04 17:04:24 +08:00
										 |  |  | 		sql := strings.Builder{} | 
					
						
							|  |  |  | 		sql.Write([]byte("UPDATE folder SET ")) | 
					
						
							|  |  |  | 		columnsToUpdate := []string{"updated = ?"} | 
					
						
							|  |  |  | 		args := []interface{}{cmd.Folder.Updated} | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		if cmd.NewDescription != nil { | 
					
						
							| 
									
										
										
										
											2022-11-04 17:04:24 +08:00
										 |  |  | 			columnsToUpdate = append(columnsToUpdate, "description = ?") | 
					
						
							|  |  |  | 			cmd.Folder.Description = *cmd.NewDescription | 
					
						
							|  |  |  | 			args = append(args, cmd.Folder.Description) | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cmd.NewTitle != nil { | 
					
						
							| 
									
										
										
										
											2022-11-04 17:04:24 +08:00
										 |  |  | 			columnsToUpdate = append(columnsToUpdate, "title = ?") | 
					
						
							|  |  |  | 			cmd.Folder.Title = *cmd.NewTitle | 
					
						
							|  |  |  | 			args = append(args, cmd.Folder.Title) | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cmd.NewUID != nil { | 
					
						
							| 
									
										
										
										
											2022-11-04 17:04:24 +08:00
										 |  |  | 			columnsToUpdate = append(columnsToUpdate, "uid = ?") | 
					
						
							|  |  |  | 			cmd.Folder.UID = *cmd.NewUID | 
					
						
							|  |  |  | 			args = append(args, cmd.Folder.UID) | 
					
						
							| 
									
										
										
										
											2022-11-08 18:33:13 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-04 17:04:24 +08:00
										 |  |  | 		if len(columnsToUpdate) == 0 { | 
					
						
							|  |  |  | 			return folder.ErrBadRequest.Errorf("no columns to update") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		sql.Write([]byte(strings.Join(columnsToUpdate, ", "))) | 
					
						
							|  |  |  | 		sql.Write([]byte(" WHERE uid = ? AND org_id = ?")) | 
					
						
							|  |  |  | 		args = append(args, existingUID, cmd.Folder.OrgID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		args = append([]interface{}{sql.String()}, args...) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		res, err := sess.Exec(args...) | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return folder.ErrDatabaseError.Errorf("failed to update folder: %w", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		affected, err := res.RowsAffected() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return folder.ErrInternal.Errorf("failed to get affected row: %w", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if affected == 0 { | 
					
						
							|  |  |  | 			return folder.ErrInternal.Errorf("no folders are updated") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | 	return cmd.Folder, err | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | func (ss *sqlStore) Get(ctx context.Context, q folder.GetFolderQuery) (*folder.Folder, error) { | 
					
						
							|  |  |  | 	foldr := &folder.Folder{} | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | 	err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		exists := false | 
					
						
							|  |  |  | 		var err error | 
					
						
							|  |  |  | 		switch { | 
					
						
							|  |  |  | 		case q.ID != nil: | 
					
						
							|  |  |  | 			exists, err = sess.SQL("SELECT * FROM folder WHERE id = ?", q.ID).Get(foldr) | 
					
						
							|  |  |  | 		case q.Title != nil: | 
					
						
							|  |  |  | 			exists, err = sess.SQL("SELECT * FROM folder WHERE title = ? AND org_id = ?", q.Title, q.OrgID).Get(foldr) | 
					
						
							|  |  |  | 		case q.UID != nil: | 
					
						
							|  |  |  | 			exists, err = sess.SQL("SELECT * FROM folder WHERE uid = ? AND org_id = ?", q.UID, q.OrgID).Get(foldr) | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return folder.ErrBadRequest.Errorf("one of ID, UID, or Title must be included in the command") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 			return folder.ErrDatabaseError.Errorf("failed to get folder: %w", err) | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if !exists { | 
					
						
							|  |  |  | 			return folder.ErrFolderNotFound.Errorf("folder not found") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2022-12-01 00:12:56 +08:00
										 |  |  | 	foldr.Url = models.GetFolderUrl(foldr.UID, slugify.Slugify(foldr.Title)) | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | 	return foldr, err | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | func (ss *sqlStore) GetParents(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) { | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 	var folders []*folder.Folder | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 	recQuery := ` | 
					
						
							|  |  |  | 		WITH RECURSIVE RecQry AS ( | 
					
						
							|  |  |  | 			SELECT * FROM folder WHERE uid = ? AND org_id = ? | 
					
						
							|  |  |  | 			UNION ALL SELECT f.* FROM folder f INNER JOIN RecQry r ON f.uid = r.parent_uid and f.org_id = r.org_id | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 		) | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		SELECT * FROM RecQry; | 
					
						
							|  |  |  | 	` | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-09 03:53:05 +08:00
										 |  |  | 	if err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		err := sess.SQL(recQuery, q.UID, q.OrgID).Find(&folders) | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 			return folder.ErrDatabaseError.Errorf("failed to get folder parents: %w", err) | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2022-11-09 03:53:05 +08:00
										 |  |  | 	}); 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 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-11-25 02:28:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if len(folders) < 1 { | 
					
						
							|  |  |  | 		// the query is expected to return at least the same folder
 | 
					
						
							|  |  |  | 		// if it's empty it means that the folder does not exist
 | 
					
						
							|  |  |  | 		return nil, folder.ErrFolderNotFound | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-09 03:53:05 +08:00
										 |  |  | 	return util.Reverse(folders[1:]), nil | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | func (ss *sqlStore) GetChildren(ctx context.Context, q folder.GetTreeQuery) ([]*folder.Folder, error) { | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | 	var folders []*folder.Folder | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | 	err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 		sql := strings.Builder{} | 
					
						
							| 
									
										
										
										
											2022-11-28 23:48:44 +08:00
										 |  |  | 		sql.Write([]byte("SELECT * FROM folder WHERE parent_uid=? AND org_id=? ORDER BY id")) | 
					
						
							| 
									
										
										
										
											2022-11-03 21:21:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if q.Limit != 0 { | 
					
						
							|  |  |  | 			var offset int64 = 1 | 
					
						
							|  |  |  | 			if q.Page != 0 { | 
					
						
							|  |  |  | 				offset = q.Page | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			sql.Write([]byte(ss.db.GetDialect().LimitOffset(q.Limit, offset))) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		err := sess.SQL(sql.String(), q.UID, q.OrgID).Find(&folders) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return folder.ErrDatabaseError.Errorf("failed to get folder children: %w", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2022-10-28 21:35:49 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 	return folders, err | 
					
						
							| 
									
										
										
										
											2022-10-26 23:52:01 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-09 03:53:05 +08:00
										 |  |  | 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) | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2022-11-09 03:53:05 +08:00
										 |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if !ok { | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			folders = append(folders, f) | 
					
						
							|  |  |  | 			uid = f.ParentUID | 
					
						
							|  |  |  | 			if len(folders) > folder.MaxNestedFolderDepth { | 
					
						
							|  |  |  | 				return folder.ErrFolderTooDeep | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2022-11-28 23:48:44 +08:00
										 |  |  | 	return util.Reverse(folders), err | 
					
						
							| 
									
										
										
										
											2022-10-29 02:07:25 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-12-08 21:49:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (ss *sqlStore) GetHeight(ctx context.Context, foldrUID string, orgID int64, parentUID *string) (int, error) { | 
					
						
							|  |  |  | 	height := -1 | 
					
						
							|  |  |  | 	queue := []string{foldrUID} | 
					
						
							|  |  |  | 	for len(queue) > 0 { | 
					
						
							|  |  |  | 		length := len(queue) | 
					
						
							|  |  |  | 		height++ | 
					
						
							|  |  |  | 		for i := 0; i < length; i++ { | 
					
						
							|  |  |  | 			ele := queue[0] | 
					
						
							|  |  |  | 			queue = queue[1:] | 
					
						
							|  |  |  | 			if parentUID != nil && *parentUID == ele { | 
					
						
							|  |  |  | 				return 0, folder.ErrCircularReference | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			folders, err := ss.GetChildren(ctx, folder.GetTreeQuery{UID: ele, OrgID: orgID}) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return 0, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for _, f := range folders { | 
					
						
							|  |  |  | 				queue = append(queue, f.UID) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return height, nil | 
					
						
							|  |  |  | } |