The manual on ALTER FUNCTION
is clear on that:
You must own the function to use
ALTER FUNCTION
. To change a function’s
schema, you must also haveCREATE
privilege on the new schema.
To alter the owner, you must also be a direct or indirect
member of the new owning role, and that role must haveCREATE
privilege on the function’s schema. (These restrictions enforce that
altering the owner doesn’t do anything you couldn’t do by dropping and
recreating the function. However, a superuser can alter ownership of
any function anyway.)
Bold emphasis mine.
You also need a couple of basic privileges to create functions. Per documentation:
To be able to define a function, the user must have the
USAGE
privilege on the language.
…To be able to create a function, you must have
USAGE
privilege on the argument types and the return type.
The simple solution would be make changes to functions as superuser. (Default superuser is postgres
, but any user can be made superuser.)
If you really need to change ownership on all functions, this would do the trick:
SELECT string_agg('ALTER FUNCTION '
|| quote_ident(n.nspname) || '.'
|| quote_ident(p.proname) || '('
|| pg_catalog.pg_get_function_identity_arguments(p.oid)
|| ') OWNER TO foo;'
, E'n') AS _sql
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_%'
Restricted to the public
schema.
For more details and explanation refer to this more complete answer on dba.SE.
Also closely related:
DROP FUNCTION without knowing the number/type of parameters?
I’m trying to debug an instance where I try to create a function with a special role "myrole"
and the operation fails with
ERROR: must be owner of function refresh_view
Other functions can be created successfully — it’s only this single function that is failing.
SET ROLE to "myrole";
CREATE OR REPLACE FUNCTION refresh_view(schema_name text, table_name text)
RETURNS void
SECURITY DEFINER
AS $$
DECLARE sql text;
BEGIN
sql := 'REFRESH MATERIALIZED VIEW ' || quote_ident(schema_name) || '.' || quote_ident(table_name) || ' with data';
EXECUTE sql;
RETURN;
END;
$$ LANGUAGE plpgsql;
asked Jan 10, 2018 at 10:41
1
The function already exists and is owned by a different role.
Only the owner or a superuser can DROP
and ALTER
objects, and the same applies for CREATE OR REPLACE FUNCTION
if the function already exists.
answered Jan 10, 2018 at 10:43
Laurenz AlbeLaurenz Albe
192k17 gold badges177 silver badges233 bronze badges
1
Что такое grant
параметр/трюк, который мне нужно предоставить текущему пользователю ( «userA» ), чтобы он мог изменить владельца объекта, принадлежащего другому пользователю ( «userC» )?
Точнее, таблица контактов принадлежит пользователю C, и когда я выполняю следующий запрос для изменения владельца к пользователю B, связанному с userA:
alter table contact owner to userB;
Я получаю эту ошибку:
ERROR: must be owner of relation contact
Но у пользователяA все необходимые права для этого обычно (опция предоставления «create on schema» должна быть достаточной):
grant select,insert,update,delete on all tables in schema public to userA;
grant select,usage,update on all sequences in schema public to userA;
grant execute on all functions in schema public to userA;
grant references, trigger on all tables in schema public to userA;
grant create on schema public to userA;
grant usage on schema public to userA;
Thks
Выход командной строки:
[email protected]:~# psql -U userA myDatabase
myDataBase=>dt contact
List of relations
Schema | Name | Type | Owner
-------+---------+----------+---------
public | contact | table | userC
(1 row)
myDataBase=>
myDataBase=>alter table contact owner to userB;
ERROR: must be owner of relation public.contact
myDataBase=>
Ответ 1
Благодаря комментарию Майка, я перечитал документ, и я понял, что мой текущий пользователь (ака. userA, который уже имеет привилегию создания) не был прямым/косвенным членом новой собственной роли…
Итак, решение было довольно простым, я только что сделал этот грант:
grant userB to userA;
Что все люди; -)
Update:
Другое требование состоит в том, что объект должен принадлежать пользователю userA перед его изменением…
Ответ 2
Из прекрасного руководства.
Вы должны владеть таблицей, чтобы использовать ALTER TABLE.
Или быть суперпользователем базы данных.
ОШИБКА: должен быть владельцем отношения
Сообщения об ошибках PostgreSQL обычно находятся на месте. Это одно место.
Какую опцию / трюк grant
мне нужно дать текущему пользователю (« userA «), чтобы он мог изменить владельца объекта, принадлежащего другому пользователю (« userC «)?
Точнее, таблица contact принадлежит userC , и когда я выполняю следующий запрос для смены владельца на userB , связанный с userA :
alter table contact owner to userB;
Я получаю такую ошибку:
ERROR: must be owner of relation contact
Но userA имеет все необходимые права, чтобы делать это в обычном режиме (параметра предоставления « create on schema » должно быть достаточно):
grant select,insert,update,delete on all tables in schema public to userA;
grant select,usage,update on all sequences in schema public to userA;
grant execute on all functions in schema public to userA;
grant references, trigger on all tables in schema public to userA;
grant create on schema public to userA;
grant usage on schema public to userA;
Спасибо
Вывод командной строки:
root@server:~# psql -U userA myDatabase
myDataBase=>dt contact
List of relations
Schema | Name | Type | Owner
-------+---------+----------+---------
public | contact | table | userC
(1 row)
myDataBase=>
myDataBase=>alter table contact owner to userB;
ERROR: must be owner of relation public.contact
myDataBase=>
3 ответа
Лучший ответ
Благодаря комментарию Майка я перечитал документ и понял, что мой текущий пользователь (т.е. userA, у которого уже есть привилегия create ) не был прямым / косвенным членом новой роли владельца …
Итак, решение было довольно простым — я только что выполнил грант:
grant userB to userA;
Это все, ребята
Обновить:
Другое требование состоит в том, что объект должен принадлежать пользователю userA до его изменения …
107
Marcus Campbell
15 Мар 2019 в 19:03
Это решило мою проблему: пример оператора alter table для смены владельца.
ALTER TABLE databasechangelog OWNER TO arwin_ash;
ALTER TABLE databasechangeloglock OWNER TO arwin_ash;
9
Vivek
18 Янв 2020 в 20:40
Из прекрасного руководства.
Вы должны владеть таблицей, чтобы использовать ALTER TABLE.
Или станьте суперпользователем базы данных.
ОШИБКА: должно быть владельцем контакта
Сообщения об ошибках PostgreSQL обычно появляются точно. Это место на высоте.
16
Mike Sherrill ‘Cat Recall’
18 Фев 2015 в 13:44
В руководстве по ALTER FUNCTION
ясно, что:
Вы должны использовать функцию для использования
ALTER FUNCTION
. Чтобы изменить схему функции, вы также должны иметь привилегиюCREATE
для новой схемы. Чтобы изменить владельца, вы также должны быть прямым или косвенным членом новой собственной роли, и эта роль должна иметь привилегиюCREATE
в схеме функций. (Эти ограничения приводят к тому, что изменение владельца не делает ничего, что вы не могли бы сделать, отбрасывая и воссоздавая функцию. Однако суперпользователь может в любом случае изменить право собственности на любую функцию.)
Смелый акцент мой.
Для создания функций вам также потребуется несколько основных привилегий. По документации:
Чтобы иметь возможность определять функцию, пользователь должен иметь привилегию
USAGE
на языке.
…Чтобы иметь возможность создавать функцию, вы должны иметь привилегии
USAGE
для типов аргументов и типа возвращаемого значения.
Простым решением будет внесение изменений в функции суперпользователя. (По умолчанию суперпользователь — postgres
, но любой пользователь может быть суперпользователем.)
Если вам действительно нужно изменить право собственности на все функции, это будет делать трюк:
SELECT string_agg('ALTER FUNCTION '
|| quote_ident(n.nspname) || '.'
|| quote_ident(p.proname) || '('
|| pg_catalog.pg_get_function_identity_arguments(p.oid)
|| ') OWNER TO foo;'
, E'n') AS _sql
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_%'
Ограничено public
схемой.
Для получения дополнительной информации и объяснения обратитесь к этому более полному ответу на dba.SE.
Также тесно связаны:
DROP FUNCTION, не зная количество/тип параметров?