¿Hay algún medio para establecer al propietario de todos los objetos en una base de datos PostgreSQL al mismo tiempo?
-
16-10-2019 - |
Pregunta
https://stackoverflow.com/questions/1348126/modify-owner-on-all-tables-simultaneyly-in-postgresql Describe algunas formas ingeniosas de cambiar la tabla y otros objetos a un usuario específico, y funciona a la mañana, sin embargo, todas las sugerencias parecen ignorar las funciones que creé.
¿Existe una manera bastante fácil de restablecer el propietario de todos los objetos en la base de datos, incluidas las funciones? Hacerlo a mano es muy indeseable.
Solución 5
Bueno, no encontré un proceso de un solo paso, pero esto se encarga de todos los objetos que puedo ver en mi base de datos:
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);
Otros consejos
Solo deberías nunca manipular catálogos del sistema directamente, si sabe exactamente lo que está haciendo. Puede tener efectos secundarios inesperados. O puede corromper la base de datos (o todo el clúster de la base de datos) más allá de la reparación.
Respuesta de Jeremy, mientras que básicamente hace el truco, es No recomendable para el público en general. Cambia incondicionalmente todas las funciones en un esquema. ¿Está seguro de que no hay funciones del sistema afectadas o funciones instaladas por un módulo adicional?
También sería inútil cambiar al propietario de las funciones que ya pertenecen al propietario designado.
Primero, verifique si REASSIGN OWNED
podría funcionar para ti:
Cambiar la propiedad de los objetos de la base de datos propiedad de un rol de base de datos
Debe enumerar todos los roles para ser repudiado explícitamente. Pero También reasigna funciones.
Asignar todos Funciones (y no otros objetos) en un esquema dado a un nuevo propietario (opcionalmente independientemente del propietario anterior):
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_%'
Esto genera el Comandos SQL canónicos ALTER FUNCTION ...
cambiar todos funciones (en el esquema especificado). Puede inspeccionar los comandos antes de ejecutarlos, uno por uno o todos a la vez:
ALTER FUNCTION public.bar(text, text) OWNER TO foo;
ALTER FUNCTION public.foo(x integer) OWNER TO foo;
...
Incluí algunos comentados WHERE
Cláusulas que puede usar para filtrar los resultados.
El elenco a regprocedure
produce un nombre de función válido con parámetros, doble cotizado cuando sea necesario, esquema: calificado cuando sea necesario para la actual search_path
.
La función agregada string_agg () Requiere PostgreSQL 9.0 o posterior. En la versión anterior sustituto con array_agg()
y array_to_string()
.
Tú pudo poner todo esto en un DO
declaración o una función como se demuestra en esta respuesta relacionada:
En Postgres 9.5 o más tarde, puede simplificar la consulta usando nuevo Tipos de identificadores de objetos regnamespace
y 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_%'
Utilizo esta función para alterar al propietario de tablas, funciones, tipos, etc. Puede cambiar la consulta de los cursores para adaptarlo a sus necesidades.
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;
Luego solo ejecuto (si desea la salida de depuración, simplemente establezca el segundo parámetro en verdadero):
SELECT fn_setowner('demo', false);
DROP FUNCTION fn_setowner(varchar(30), boolean);
Esto debería funcionar para las funciones:
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
Puedes usar el comando reasignado
Simplemente inicie sesión en la base de datos con Superuser y ejecute a continuación
REASSIGN OWNED BY [old_user] TO [new_user];
Esto cambia todos los objetos, es decir, tablas, secuencia, función, etc., propiedad de Old_role al nuevo rol. No tiene que pensar en qué tipo de objetos tiene el usuario, todos se cambiarán. Esto cambia los objetos solo si quieres cambiar la propiedad de esa base de datos en sí solo usar ALTER DATABASE name OWNER TO new_owner
Este es el mejor método, ya que habrá n número de tablas, secuencia en lugar de ir a bucles y scripts bash