PostgreSQLデータベースにすべてのオブジェクトの所有者を同時に設定する手段はありますか?
-
16-10-2019 - |
質問
https://stackoverflow.com/questions/1348126/modify-Onder-on-all-All-tables-simultanes-in-postgreSql テーブルやその他のオブジェクトを特定のユーザーに変更するための気の利いた方法について説明し、水泳に動作しますが、すべての提案は私が作成した機能を無視しているようです。
関数を含むデータベース内のすべてのオブジェクトの所有者をリセットするかなり簡単な方法はありますか?手でそれをすることは非常に望ましくありません。
解決 5
まあ、私はワンステップのプロセスを見つけませんでしたが、これは私のデータベースで見ることができるすべてのオブジェクトの世話をします:
update pg_class
SET relowner = (SELECT oid FROM pg_roles WHERE rolname = 'foo')
where relnamespace = (select oid
from pg_namespace
where nspname = 'public'
limit 1);
update pg_proc
set proowner = (select oid from pg_roles where rolname = 'foo')
where pronamespace = (select oid
from pg_namespace
where nspname = 'public'
limit 1);
他のヒント
あなたはこれまでだけすべきです システムカタログを操作します 直接、自分が何をしているのかを正確に知っている場合。予期しない副作用があるかもしれません。または、修理を超えてデータベース(またはデータベースクラスター全体)を破損することもできます。
ジェレミーの答え, 、基本的にトリックをしている間です お勧めできません 一般大衆のために。すべての機能をスキーマ内で無条件に変更します。影響を受けるシステム関数がないか、追加のモジュールによってインストールされた関数がないことを確認しますか?
また、すでに指定された所有者に属している機能の所有者を変更することは無意味です。
最初に、かどうかを確認します REASSIGN OWNED
あなたのために働くことができます:
データベースの役割が所有するデータベースオブジェクトの所有権を変更する
明示的に否認されるすべての役割をリストする必要があります。しかし、それ また、関数を再割り当てします.
割り当てます すべて 新しい所有者に対する特定のスキーマ内の関数(および他のオブジェクトはありません)(以前の所有者に関係なく):
SELECT string_agg('ALTER FUNCTION ' || oid::regprocedure || ' OWNER TO foo;', E'\n') AS ddl
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname = 'public';
-- AND p.relowner <> (SELECT oid FROM pg_roles WHERE rolname = 'foo')
-- AND p.proname ~~ 'f_%'
これは、を生成します 標準的なSQLコマンド ALTER FUNCTION ...
変更する すべて 関数(指定されたスキーマ内)。コマンドを実行する前に、1つまたはすべてを一度に検査することができます。
ALTER FUNCTION public.bar(text, text) OWNER TO foo;
ALTER FUNCTION public.foo(x integer) OWNER TO foo;
...
コメントを含めました WHERE
結果をフィルタリングするために使用したい場合があります。
キャスト regprocedure
必要に応じて二重引用されたパラメーターを備えた有効な関数名を作成します。 search_path
.
集約関数 string_agg() PostgreSQL 9.0以降が必要です。古いバージョンでは、 array_agg()
と array_to_string()
.
君 たぶん......だろう これらすべてをaに入れます DO
この関連する答えで示されているようなステートメントまたは関数:
Postgresで 9.5 または後で、newを使用してクエリを簡素化できます オブジェクト識別子タイプ regnamespace
と regrole
:
SELECT string_agg('ALTER FUNCTION '|| oid::regprocedure || ' OWNER TO foo;', E'\n') AS ddl
FROM pg_catalog.pg_proc
WHERE pronamespace = 'public'::regnamespace;
-- AND relowner <> 'foo'::regrole
-- AND proname ~~ 'f_%'
この関数を使用して、テーブル、関数、タイプなどの所有者を変更します。カーソルのクエリを変更して、ニーズに合わせて適応できます。
CREATE OR REPLACE FUNCTION fn_setowner(varchar(50), boolean) RETURNS void AS
$BODY$
DECLARE
p_owner ALIAS FOR $1;
p_debug ALIAS FOR $2;
v_i integer := 0;
v_sql text;
-- CURSORS
-- SCHEMA
pesquemas CURSOR FOR
SELECT quote_ident(schema_name) as nombre_esquema from information_schema.schemata WHERE schema_name NOT LIKE 'pg_%'
and schema_name NOT IN ('information_schema') ORDER BY 1 ASC;
-- TABLE
ptablas CURSOR FOR
SELECT quote_ident(table_schema) || '.' || quote_ident(table_name) as nombre_tabla, * FROM information_schema.tables
WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
AND table_type <> 'FOREIGN TABLE' ORDER BY 1 ASC;
-- FUNCTION
pfunciones CURSOR FOR
SELECT quote_ident(b.nspname) || '.' || quote_ident(a.proname) || '(' || pg_catalog.oidvectortypes(a.proargtypes) || ')' as nombre_function
FROM pg_proc a INNER JOIN pg_namespace b on a.pronamespace = b.oid
WHERE b.nspname NOT IN ('pg_catalog', 'information_schema') AND proisagg = 'f'
AND a.proname not like 'fsym_%' AND a.proname not like 'dblink%' ORDER BY 1 ASC;
-- SEQUENCE
psecuencias CURSOR FOR
SELECT quote_ident(sequence_schema) || '.' || quote_ident(sequence_name) as nombre_secuencia FROM information_schema.sequences
WHERE sequence_schema NOT IN ('pg_catalog', 'information_schema') ORDER BY 1 ASC;
-- TYPE
ptipos CURSOR FOR
SELECT quote_ident(n.nspname) || '.' || quote_ident(t.typname) as nombre_tipo
FROM pg_type t
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid))
AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)
AND n.nspname NOT IN ('pg_catalog', 'information_schema') ORDER BY 1 ASC;
BEGIN
-- CHECK LOGIN
IF NOT EXISTS (SELECT 1 FROM pg_user WHERE usename = p_owner) THEN
RAISE EXCEPTION 'Login role not exists --> %', p_owner
USING HINT = 'Please specify correct login and try again.';
END IF;
v_i = 0;
if (p_debug) THEN
RAISE NOTICE '--########## CHANGE SCHEMA OWNER ##########--';
END IF;
FOR resquema IN pesquemas LOOP
v_sql = 'ALTER SCHEMA ' || resquema.nombre_esquema || ' OWNER TO ' || quote_ident(p_owner) || ';';
if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
EXECUTE v_sql;
v_i = v_i + 1;
END LOOP;
if (p_debug) THEN
RAISE NOTICE '--@@@@@@ SCHEMAS WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
END IF;
v_i = 0;
if (p_debug) THEN
RAISE NOTICE '--########## CHANGE TABLE OWNER ##########--';
END IF;
FOR rtables IN ptablas LOOP
v_sql = 'ALTER TABLE ' || rtables.nombre_tabla || ' OWNER TO ' || quote_ident(p_owner) || ';';
if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
EXECUTE v_sql;
v_i = v_i + 1;
END LOOP;
if (p_debug) THEN
RAISE NOTICE '--@@@@@@ TABLES WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
END IF;
v_i = 0;
if (p_debug) THEN
RAISE NOTICE '--########## CHANGE FUNCTION OWNER ##########--';
END IF;
FOR rfunction IN pfunciones LOOP
v_sql = 'ALTER FUNCTION ' || rfunction.nombre_function || ' OWNER TO ' || quote_ident(p_owner) || ';';
if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
EXECUTE v_sql;
v_i = v_i + 1;
END LOOP;
if (p_debug) THEN
RAISE NOTICE '--@@@@@@ FUNCTIONS WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
END IF;
v_i = 0;
if (p_debug) THEN
RAISE NOTICE '--########## CHANGE SEQUENCE OWNER ########## --';
END IF;
FOR rsecuencias IN psecuencias LOOP
v_sql = 'ALTER TABLE ' || rsecuencias.nombre_secuencia || ' OWNER TO ' || quote_ident(p_owner) || ';';
if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
EXECUTE v_sql;
v_i = v_i + 1;
END LOOP;
if (p_debug) THEN
RAISE NOTICE '--@@@@@@ SEQUENCES WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
END IF;
v_i = 0;
if (p_debug) THEN
RAISE NOTICE '--########## CHANGE TYPE OWNER ##########--';
END IF;
FOR rtipos IN ptipos LOOP
v_sql = 'ALTER TYPE ' || rtipos.nombre_tipo || ' OWNER TO ' || quote_ident(p_owner) || ';';
if (p_debug) THEN RAISE NOTICE '%', v_sql; END IF;
EXECUTE v_sql;
v_i = v_i + 1;
END LOOP;
if (p_debug) THEN
RAISE NOTICE '--@@@@@@ TYPES WITH OWNER % TOTAL = % @@@@@@--', p_owner, CAST(v_i AS VARCHAR);
END IF;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
次に、実行するだけです(出力をデバッグしたい場合は、2番目のパラメーターをtrueに設定するだけです):
SELECT fn_setowner('demo', false);
DROP FUNCTION fn_setowner(varchar(30), boolean);
これは機能のために機能するはずです:
IFS=$'\n'
for fnc in `psql -qAt -c "SELECT '\"' || p.proname||'\"' || '(' || pg_catalog.pg_get_function_identity_arguments(p.oid) || ')' FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_proc p ON p.pronamespace = n.oid WHERE n.nspname = 'public';" YOUR_DB`
do
psql -c "alter function $fnc owner to NEW_OWNER" YOUR_DB
done
再割り当て所有コマンドを使用できます
スーパーユーザーを使用してデータベースにログインして、以下を実行します
REASSIGN OWNED BY [old_user] TO [new_user];
これにより、すべてのオブジェクトが変更されます。つまり、Old_roleが所有するテーブル、シーケンス、関数など、新しい役割になります。ユーザーが持っているオブジェクトの種類について考える必要はありません。それらはすべて変更されます。これにより、そのデータベース自体の所有権を変更したい場合にのみオブジェクトが変更されます。 ALTER DATABASE name OWNER TO new_owner
これは、ループとバッシュスクリプトを使用するのではなく、nの数のテーブル、シーケンスがあるため、最良の方法です。