Подход pg_dump
приятен и прост, однако он не работает с таблицами в других схемах, так как вывод не квалифицирует таблицу с именем схемы. Вместо этого он генерирует:
SET search_path = foo, pg_catalog;
...
GRANT SELECT ON foo_table to foo_user;
и не сможет предоставить привилегии несуществующему public.foo_table
отношению.
Кроме того, если у вас есть отношения с одним и тем же именем в разных схемах, вам необходимо убедиться, что вы переименовываете только таблицу в указанной схеме. Я начал взламывать базу сценариев bash, чтобы позаботиться об этом, но она стала немного громоздкой, поэтому я переключился на perl.
Использование: transfer-acl old-qualified-relation=new-qualified-relation
например. transfer-acl foo.foo_table=foo.bar_table
будет применять гранты на foo.foo_table
к foo.bar_table
. Я не реализовал никакой REVOKE
перезаписи, потому что я не смог получить дамп для его генерации.
#! /usr/bin/perl
use strict;
use warnings;
my %rename = map {(split '=')} @ARGV;
open my $dump, '-|', qw(pg_dump customer -s), map {('-t', $_)} keys %rename
or die "Cannot open pipe from pg_dump: $!\n";
my $schema = 'public';
while (<$dump>) {
if (/^SET search_path = (\w+)/) {
$schema = $1;
}
elsif (/^(GRANT .*? ON TABLE )(\w+)( TO (?:[^;]+);)$/) {
my $fq_table = "$schema." . $2; # fully-qualified schema.table
print "$1$rename{$fq_table}$3\n" if exists $rename{$fq_table};
}
}
Перенесите результаты этого к psql
и все готово.