From 54a5fd55e14f8f458e862e007b8720b7b31ff034 Mon Sep 17 00:00:00 2001 From: divyam234 <47589864+divyam234@users.noreply.github.com> Date: Tue, 11 Jun 2024 19:29:05 +0530 Subject: [PATCH] refactor: improve deletion --- .../20240611190605_create_functions.sql | 83 +++++++++++++++++++ pkg/controller/file.go | 2 +- pkg/schemas/file.go | 4 + pkg/services/file.go | 22 ++--- 4 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 internal/database/migrations/20240611190605_create_functions.sql diff --git a/internal/database/migrations/20240611190605_create_functions.sql b/internal/database/migrations/20240611190605_create_functions.sql new file mode 100644 index 00000000..a5dd090d --- /dev/null +++ b/internal/database/migrations/20240611190605_create_functions.sql @@ -0,0 +1,83 @@ +-- +goose Up +-- +goose StatementBegin +DROP PROCEDURE IF EXISTS teldrive.delete_files; + +CREATE OR REPLACE PROCEDURE teldrive.delete_folder_recursive( + IN src text, + IN u_id bigint +) +LANGUAGE plpgsql +AS $procedure$ +DECLARE + folder_id text; + folder_ids text[]; +BEGIN + + IF position('/' in src) = 1 THEN + select id into folder_id from teldrive.get_file_from_path(src,u_id); + IF folder_id IS NULL THEN + RAISE EXCEPTION 'source not found'; + END IF; + ELSE + folder_id := src; + IF NOT EXISTS (SELECT 1 FROM teldrive.files WHERE id = folder_id) THEN + RAISE EXCEPTION 'source not found'; + END IF; + END IF; + + WITH RECURSIVE folder_tree AS ( + SELECT id + FROM teldrive.files + WHERE id = folder_id + AND user_id = u_id and type='folder' + + UNION ALL + + SELECT f.id + FROM teldrive.files f + JOIN folder_tree ft ON f.parent_id = ft.id + WHERE f.user_id = u_id and f.type='folder' + ) SELECT array_agg(id) INTO folder_ids FROM folder_tree; + + UPDATE teldrive.files + SET status = 'pending_deletion' + WHERE parent_id = ANY (folder_ids) and type='file' and user_id = u_id; + + DELETE FROM teldrive.files + WHERE id = ANY (folder_ids) AND user_id = u_id; +END; +$procedure$; + +CREATE OR REPLACE PROCEDURE teldrive.delete_files_bulk( + IN file_ids text[], + IN u_id bigint +) +LANGUAGE plpgsql +AS $procedure$ +DECLARE + folder_ids text[]; +BEGIN + WITH RECURSIVE folder_tree AS ( + SELECT id + FROM teldrive.files + WHERE id = ANY (file_ids) + AND user_id = u_id AND type = 'folder' + + UNION ALL + + SELECT f.id + FROM teldrive.files f + JOIN folder_tree ft ON f.parent_id = ft.id + WHERE f.user_id = u_id AND f.type = 'folder' + ) SELECT array_agg(id) INTO folder_ids FROM folder_tree; + + UPDATE teldrive.files + SET status = 'pending_deletion' + WHERE (id = ANY (file_ids) OR parent_id = ANY (folder_ids)) + AND type = 'file' AND user_id = u_id; + + DELETE FROM teldrive.files + WHERE id = ANY (folder_ids) AND user_id = u_id; +END; +$procedure$ +-- +goose StatementEnd \ No newline at end of file diff --git a/pkg/controller/file.go b/pkg/controller/file.go index 7be13baf..cdc5f537 100644 --- a/pkg/controller/file.go +++ b/pkg/controller/file.go @@ -138,7 +138,7 @@ func (fc *Controller) DeleteFiles(c *gin.Context) { userId, _ := services.GetUserAuth(c) - var payload schemas.FileOperation + var payload schemas.DeleteOperation if err := c.ShouldBindJSON(&payload); err != nil { httputil.NewError(c, http.StatusBadRequest, err) return diff --git a/pkg/schemas/file.go b/pkg/schemas/file.go index f8569dc3..22c14c7c 100644 --- a/pkg/schemas/file.go +++ b/pkg/schemas/file.go @@ -78,6 +78,10 @@ type FileOperation struct { Files []string `json:"files" binding:"required"` Destination string `json:"destination,omitempty"` } +type DeleteOperation struct { + Files []string `json:"files,omitempty"` + Source string `json:"source,omitempty"` +} type DirMove struct { Source string `json:"source" binding:"required"` diff --git a/pkg/services/file.go b/pkg/services/file.go index 646181e4..4b06246f 100644 --- a/pkg/services/file.go +++ b/pkg/services/file.go @@ -30,7 +30,6 @@ import ( "github.com/gotd/td/tg" "go.uber.org/zap" - "github.com/jackc/pgx/v5/pgtype" "gorm.io/datatypes" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -301,23 +300,24 @@ func (fs *FileService) MakeDirectory(userId int64, payload *schemas.MkDir) (*sch func (fs *FileService) MoveFiles(userId int64, payload *schemas.FileOperation) (*schemas.Message, *types.AppError) { - items := pgtype.Array[string]{ - Elements: payload.Files, - Valid: true, - Dims: []pgtype.ArrayDimension{{Length: int32(len(payload.Files)), LowerBound: 1}}, - } - - if err := fs.db.Exec("select * from teldrive.move_items(? , ? , ?)", items, payload.Destination, userId).Error; err != nil { + if err := fs.db.Exec("select * from teldrive.move_items($1 , $2 , $3)", payload.Files, payload.Destination, userId).Error; err != nil { return nil, &types.AppError{Error: err} } return &schemas.Message{Message: "files moved"}, nil } -func (fs *FileService) DeleteFiles(userId int64, payload *schemas.FileOperation) (*schemas.Message, *types.AppError) { +func (fs *FileService) DeleteFiles(userId int64, payload *schemas.DeleteOperation) (*schemas.Message, *types.AppError) { + + if payload.Source != "" { + if err := fs.db.Exec("call teldrive.delete_folder_recursive($1 , $2)", payload.Source, userId).Error; err != nil { + return nil, &types.AppError{Error: err} + } + } else if payload.Source == "" && len(payload.Files) > 0 { + if err := fs.db.Exec("call teldrive.delete_files_bulk($1 , $2)", payload.Files, userId).Error; err != nil { + return nil, &types.AppError{Error: err} + } - if err := fs.db.Exec("call teldrive.delete_files($1)", payload.Files).Error; err != nil { - return nil, &types.AppError{Error: err} } return &schemas.Message{Message: "files deleted"}, nil