¿Cómo deshabilitar temporalmente las claves externas en Amazon RDS PostgreSQL?

10

Estoy migrando el entorno de prueba existente a Amazon RDS PostgreSQL. El marco de prueba tiene una característica de recargar datos en ciertas tablas a un estado anterior. Para esto, deshabilita las claves externas, elimina los datos existentes, carga el estado de guardado y habilita nuevamente las claves externas.

Actualmente, el marco de prueba deshabilita las claves foráneas al deshabilitar todos los disparadores (por supuesto, esto requiere superusuario):

alter table tablename disable trigger all;

En RDS, esto falla con:

ERROR: permiso denegado: "RI_ConstraintTrigger_a_20164" es un activador del sistema

¿Cómo puedo desactivar temporalmente las claves foráneas en Amazon RDS PostgreSQL?

Nota: ya se ha hecho una pregunta similar ( PostgreSQL en RDS: ¿Cómo importar datos en masa con restricciones FK? ) Pero se trataba específicamente de la importación sin conexión y la solución también es específica para la importación sin conexión.

Piotr Findeisen
fuente
Tal vez esto debería ser una pregunta de stackoverflow?
Piotr Findeisen
En desacuerdo: está muy claramente relacionado con la administración de la base de datos.
Vérace
¿Cómo deshabilitas los FK ahora? ¿Por qué esperas que sea diferente en RDS? Además, ¿por qué no probarlo?
dezso
@dezso, gracias por el comentario. Claro, agregué el código que se usa en PostgreSQL no RDS.
Piotr Findeisen
Oh sí, de esta manera no funcionará. Pero, ¿qué hay de dejar caer y recrear las restricciones FK?
dezso

Respuestas:

11

session_replication_role

Encontré una forma alternativa de deshabilitar claves externas: https://stackoverflow.com/a/18709987

set session_replication_role = replica;

Y volver a habilitarlos con

set session_replication_role = default;

Esto funciona en RDS pero aún requiere privilegios inusuales (es decir, no se otorga por defecto).

soltando y recreando FKs

La solución alternativa es, como se sugiere en los comentarios, eliminar temporalmente los FK. Esto brinda una ventaja adicional de que los datos se verifican cuando se reactivan los FK.

Goteante

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 $$;

Recreando

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
fuente