From 7e5e3adf5fa6a26d77a38c82c953986c9ae8d476 Mon Sep 17 00:00:00 2001 From: divyam234 <47589864+divyam234@users.noreply.github.com> Date: Fri, 7 Jun 2024 20:19:48 +0530 Subject: [PATCH] refactor: list files by parentId explicitly --- .../20240607114052_modify_functions.sql | 49 +++++++++++++++++++ pkg/services/file.go | 25 +++++----- 2 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 internal/database/migrations/20240607114052_modify_functions.sql diff --git a/internal/database/migrations/20240607114052_modify_functions.sql b/internal/database/migrations/20240607114052_modify_functions.sql new file mode 100644 index 00000000..5770c256 --- /dev/null +++ b/internal/database/migrations/20240607114052_modify_functions.sql @@ -0,0 +1,49 @@ +-- +goose Up +-- +goose StatementBegin +CREATE OR REPLACE FUNCTION teldrive.get_file_from_path(full_path text,u_id bigint) +RETURNS setof teldrive.files AS $$ +DECLARE + target_id text; +begin + + IF full_path = '/' then + RETURN QUERY select * from teldrive.files as root where root.parent_id = 'root' and root.user_id = u_id; + END IF; + + WITH RECURSIVE dir_hierarchy AS ( + SELECT + root.id, + root.name, + root.parent_id, + 0 AS depth, + '' as path + FROM + teldrive.files as root + WHERE + root.parent_id = 'root' AND root.user_id = u_id + + UNION ALL + + SELECT + f.id, + f.name, + f.parent_id, + dh.depth + 1 AS depth, + dh.path || '/' || f.name + FROM + teldrive.files f + JOIN + dir_hierarchy dh ON dh.id = f.parent_id + WHERE f.type = 'folder' AND f.user_id = u_id + ) + + SELECT id into target_id FROM dir_hierarchy dh + WHERE dh.path = full_path + ORDER BY dh.depth DESC + LIMIT 1; + + RETURN QUERY select * from teldrive.files where id=target_id; + +END; +$$ LANGUAGE plpgsql; +-- +goose StatementEnd diff --git a/pkg/services/file.go b/pkg/services/file.go index 80242b78..646181e4 100644 --- a/pkg/services/file.go +++ b/pkg/services/file.go @@ -155,33 +155,32 @@ func (fs *FileService) GetFileByID(id string) (*schemas.FileOutFull, *types.AppE func (fs *FileService) ListFiles(userId int64, fquery *schemas.FileQuery) (*schemas.FileResponse, *types.AppError) { - var ( - parent *models.File - err error - ) + var parentID string - if fquery.Path != "" { - parent, err = fs.getFileFromPath(fquery.Path, userId) + if fquery.Path != "" && fquery.ParentID == "" { + parent, err := fs.getFileFromPath(fquery.Path, userId) if err != nil { return nil, &types.AppError{Error: err, Code: http.StatusNotFound} } + parentID = parent.Id + } else if fquery.ParentID != "" { + parentID = fquery.ParentID } query := fs.db.Limit(fquery.PerPage) setOrderFilter(query, fquery) if fquery.Op == "list" { - filter := &models.File{UserID: userId, Status: "active"} - query.Order("type DESC").Order(getOrder(fquery)).Where("parent_id = ?", parent.Id). - Model(filter).Where(&filter) + filter := &models.File{UserID: userId, Status: "active", ParentID: parentID} + query.Order("type DESC").Order(getOrder(fquery)).Model(filter).Where(&filter) } else if fquery.Op == "find" { - if !fquery.DeepSearch && parent != nil && (fquery.Name != "" || fquery.Query != "") { - query.Where("parent_id = ?", parent.Id) + if !fquery.DeepSearch && parentID != "" && (fquery.Name != "" || fquery.Query != "") { + query.Where("parent_id = ?", parentID) fquery.Path = "" - } else if fquery.DeepSearch && parent != nil && fquery.Query != "" { + } else if fquery.DeepSearch && parentID != "" && fquery.Query != "" { query = fs.db.Clauses(exclause.With{Recursive: true, CTEs: []exclause.CTE{{Name: "subdirs", - Subquery: exclause.Subquery{DB: fs.db.Model(&models.File{Id: parent.Id}).Select("id", "parent_id").Clauses(exclause.NewUnion("ALL ?", + Subquery: exclause.Subquery{DB: fs.db.Model(&models.File{Id: parentID}).Select("id", "parent_id").Clauses(exclause.NewUnion("ALL ?", fs.db.Table("teldrive.files as f").Select("f.id", "f.parent_id"). Joins("inner join subdirs ON f.parent_id = subdirs.id")))}}}}).Where("files.id in (select id from subdirs)") fquery.Path = ""