Postgresql: ОШИБКА: обновление или удаление в таблице «папка» нарушает ограничение внешнего ключа «fk_folder» для таблицы «актив» - PullRequest
0 голосов
/ 01 мая 2020

Мне интересно, может ли кто-нибудь из вас помочь мне с приведенной ниже ошибкой, которую я получаю от Postgres.

    ERROR:  update or delete on table "folder" violates foreign key constraint "fk_folder" on table "asset"

Моя цель - рекурсивное удаление папок и / или мягкое удаление ресурсов. , Вот как это выглядит

        DECLARE
    count_shares integer = 0;
    count_assets integer = 0;
    count_children integer = 0;
    count_updated_assets integer = 0;
    has_admin boolean = 'false';
    recursive_result boolean = 'false';
BEGIN
    RAISE INFO 'delete_folder(%, %, %, %, %, %, %)', _user_ref, _folder_id, _group_ids, _force, _move_to, _should_move, _move_shares;

    -- Do we have admin rights?
    SELECT allowed.has_admin INTO has_admin
        FROM get_folder_permissions(_user_ref, _folder_id, _group_ids) allowed
        WHERE allowed.ownership = 'owner';

    -- Any sub-folders (children)?
    SELECT count(*) INTO count_children
        FROM folder fol
        WHERE fol.parent = _folder_id;

    -- Any shares for this folder?
    SELECT count(*) INTO count_shares
        FROM folder_share shares
        WHERE shares.folder_id = _folder_id;

    -- Any assets inside this folder?
    SELECT count(*) INTO count_assets
        FROM asset ast WHERE ast.folder = _folder_id;

    RAISE INFO 'Retrieved % children, % shares and % assets for folder %', count_children, count_shares, count_assets, _folder_id;

    -- If not in force mode and assets/shares/children exist then raise exception
    IF NOT _force THEN
        IF (count_children + count_shares + count_assets) > 0 THEN
            RAISE EXCEPTION 'Cannot delete folder %, it has % children, % shares and % assets; use force or move features.', _folder_id, count_children, count_shares, count_assets USING ERRCODE ='ER422';
        END IF;
    END IF;

    -- Only remove items if we have admin permissions
    IF has_admin THEN
        IF _should_move THEN
            -- Move Sub-Folders
            IF count_children > 0 THEN
                UPDATE folder fol
                    SET parent = _move_to 
                    WHERE fol.id = _folder_id;

                RAISE INFO 'Moved % children from % to %', count_children, _folder_id, _move_to;
            END IF;

            -- Update Folder Shares
            IF count_shares > 0 THEN
                IF _move_shares THEN
                    UPDATE folder_share shares
                        SET folder_id = _move_to 
                        WHERE shares.folder_id = _folder_id;

                    RAISE INFO 'Moved % shares from % to %', count_shares, _folder_id, _move_to;
                ELSE
                    DELETE FROM folder_share
                        WHERE folder_id = _folder_id;

                    RAISE INFO 'Deleted % shares of folder %', count_shares, _folder_id;
                END IF;
            END IF;

            -- Update Assets
            IF count_assets > 0 THEN
                UPDATE asset
                    SET folder = _move_to
                    WHERE asset.folder = _folder_id;

                RAISE INFO 'Moved % assets from % to %', count_assets, _folder_id, _move_to;
            END IF;

            --Delete the empty folder
            DELETE FROM folder fol
                    WHERE fol.id = _folder_id;
        ELSE
            -- Delete Folder Shares
            IF count_shares > 0 THEN
                DELETE FROM folder_share fol_sh
                    WHERE fol_sh.folder_id = _folder_id;

                RAISE INFO 'Deleted % shares of folder %', count_shares, _folder_id;
            END IF;

            -- Delete Assets (soft delete)
            IF count_assets > 0 THEN
                -- Delete Asset Shares

                DELETE FROM asset_share
                    WHERE asset_share.asset_id
                        IN (SELECT DISTINCT asset.id FROM asset WHERE asset.folder = _folder_id);


                RAISE INFO 'Deleted asset shares, for all assets inside folder %', _folder_id;

                -- Soft Delete Assets and Reset to Root
                    UPDATE asset
                        SET deleted = CURRENT_TIMESTAMP, folder = NULL
                        WHERE folder = _folder_id;

                SELECT COUNT(*) INTO count_updated_assets
                    FROM asset WHERE asset.folder = _folder_id;

                RAISE INFO 'Soft deleted % assets from folder %', count_assets, _folder_id;
                RAISE INFO 'Soft deleted assets % pointers remaining', count_updated_assets;
            END IF;
            RAISE INFO 'Exited soft deletion of assets';

            -- Delete Children (recursive - call this function for each child)
            IF count_children > 0 THEN
                SELECT delete_folder_test(_user_ref, fol.id, _group_ids, _force, _move_to, _should_move, _move_shares) INTO recursive_result
                    FROM folder fol
                    WHERE fol.parent = _folder_id;

                RAISE INFO 'Execute delete_folder for all child folders';

                IF NOT recursive_result THEN
                    RAISE EXCEPTION 'Cannot delete child folder %.', _folder_id;
                END IF;

                DELETE FROM folder fol
                    WHERE fol.id = _folder_id;

                RAISE INFO 'Deleted child folder %', _folder_id;
                RAISE INFO 'Deleted % children of folder %', count_children, _folder_id;
            ELSE
                DELETE FROM folder fol
                    WHERE fol.id = _folder_id;

                RAISE INFO 'Child folders remaining %', count_children;
            END IF;

        END IF;

        RETURN 'true';
    ELSE
        RAISE EXCEPTION 'Cannot delete folder % as you lack admin privileges.', _folder_id USING ERRCODE ='ER403';
    END IF;

    RETURN 'false';
END

Я пытался: См. Ответ на этот пост

И считается: Удаление и повторное добавление ограничения

Но мне интересно, если кто-нибудь знает какие-либо решения для этого, любая помощь будет высоко ценится.

...