Como desativar temporariamente chaves estrangeiras no Amazon RDS PostgreSQL?

10

Estou migrando o ambiente de teste existente para o Amazon RDS PostgreSQL. A estrutura de teste possui um recurso de recarregar dados em determinadas tabelas para um estado anterior. Para isso, desativa as chaves estrangeiras, exclui os dados existentes, carrega o estado de salvamento e ativa novamente as chaves estrangeiras.

Atualmente, a estrutura de teste desabilita as chaves estrangeiras desativando todos os gatilhos (é claro, isso requer superusuário):

alter table tablename disable trigger all;

No RDS, isso falha com:

ERRO: permissão negada: "RI_ConstraintTrigger_a_20164" é um gatilho do sistema

Como posso desativar temporariamente chaves estrangeiras no Amazon RDS PostgreSQL?

Nota: pergunta semelhante já foi feita ( PostgreSQL no RDS: como importar dados em massa com restrições FK? ), Mas era especificamente sobre importação offline e a solução também é específica para importação offline.

Piotr Findeisen
fonte
Talvez essa deva ser uma questão de stackoverflow?
Piotr Findeisen
Discordo - está claramente relacionado à administração do banco de dados.
Vérace 03/04
Como você desabilita os FKs agora? Por que você espera que seja diferente no RDS? Além disso, por que não tentar a si mesmo?
Dez15
@ Dezso, obrigado pelo comentário. Claro, eu adicionei o código usado no PostgreSQL não RDS.
Piotr Findeisen
Ah, sim, desta forma, não vai funcionar. Mas que tal eliminar e recriar as restrições do FK?
Dez15

Respostas:

11

session_replication_role

Encontrei uma maneira alternativa de desativar chaves estrangeiras - https://stackoverflow.com/a/18709987

set session_replication_role = replica;

E reativá-los com

set session_replication_role = default;

Isso funciona no RDS, mas ainda requer privilégios incomuns (por exemplo, não concedidos por padrão).

descartando e recriando FKs

Solução alternativa é, conforme sugerido nos comentários, eliminar temporariamente os FKs. Isso traz uma vantagem adicional de que os dados são verificados quando os FKs são reativados.

Deixando cair

create table if not exists dropped_foreign_keys (
        seq bigserial primary key,
        sql text
);

do $$ declare t record;
begin
    for t in select conrelid::regclass::varchar table_name, conname constraint_name,
            pg_catalog.pg_get_constraintdef(r.oid, true) constraint_definition
            from pg_catalog.pg_constraint r
            where r.contype = 'f'
            -- current schema only:
            and r.connamespace = (select n.oid from pg_namespace n where n.nspname = current_schema())
        loop

        insert into dropped_foreign_keys (sql) values (
            format('alter table %s add constraint %s %s',
                quote_ident(t.table_name), quote_ident(t.constraint_name), t.constraint_definition));

        execute format('alter table %s drop constraint %s', quote_ident(t.table_name), quote_ident(t.constraint_name));

    end loop;
end $$;

Recriando

do $$ declare t record;
begin
    -- order by seq for easier troubleshooting when data does not satisfy FKs
    for t in select * from dropped_foreign_keys order by seq loop
        execute t.sql;
        delete from dropped_foreign_keys where seq = t.seq;
    end loop;
end $$;
Piotr Findeisen
fonte