2

是否可以将用户权限从 PostgreSQL 数据库中的一个表复制到另一个表?是否只是将目标表的 pg_class.relacl 列值更新为源表的值,如下所示:

UPDATE pg_class
SET relacl=(SELECT relacl FROM pg_class WHERE relname='source_table')
WHERE relname='target_table';

这似乎可行,但我是否错过了可能需要完成的其他任何事情或使用此方法的其他“陷阱”?

提前感谢您的任何回复。

4

2 回答 2

4

如果您可以使用命令行而不是 SQL,那么更安全的方法是使用 pg_dump:

pg_dump dbname -t oldtablename -s \
| egrep '^(GRANT|REVOKE)' \
| sed 's/oldtablename/newtablename/' \
| psql dbname

我假设一个unix服务器。在 Windows 上,我会使用pg_dump -s文件,手动编辑它,然后将其导入数据库。

也许您还需要复制此表拥有的序列的权限 - pg_dump 将起作用。

于 2009-12-01T14:07:03.610 回答
1

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您就可以了。

于 2019-03-25T10:23:47.480 回答