postgresql:如何用函数修改pg_catalog?

时间:2014-02-17 16:42:07

标签: postgresql plpgsql

您好我想创建一个在pg_catalog中创建表的函数,如:

CREATE OR REPLACE FUNCTION foo() RETURNS void AS $$
DECLARE

BEGIN
EXECUTE 'CREATE TABLE pg_catalog.tab(a integer)';   
        RETURN;

END;
$$ LANGUAGE plpgsql;

错误:拒绝创建“pg_catalog.tab”的权限 详细信息:目前不允许进行系统目录修改。

我编辑了我的问题以添加更多详细信息:

Real我想创建一个在删除表时启动的函数。我认为唯一的方法是在表pg_catalog.tables上创建一个触发器:

CREATE OR REPLACE FUNCTION a() RETURNS void AS $$
DECLARE
BEGIN

  EXECUTE 'CREATE TRIGGER "tt_drop" BEFORE DELETE ON pg_catalog.pg_tables EXECUTE PROCEDURE public.b()';
  RETURN;

END;
$$ LANGUAGE plpgsql;

并且在函数b中我想在删除表之前对它做一些操作...

1 个答案:

答案 0 :(得分:4)

这是出于实际和主要安全原因的禁止 - pg_catalog始终是搜索路径上的第一个,没有人可以更改它,因为PostgreSQL团队希望pg_catalog中的函数不会被自定义函数覆盖。

存在一些非常难看的技巧,但我不建议使用它。

稍微不那么难看,但仍然非常难看的是将Postgres切换到单一模式 - 有任何安全机制都关闭 - 但存在数据库损坏的高风险。因此,只有完全了解Postgres内部人员才能使用它。

回复更新的问题:

您无法在系统表上创建触发器。但是有event triggers并且它可能是你想要的(由PostgreSQL 9.3支持)。

CREATE FUNCTION test_event_trigger_for_drops()
        RETURNS event_trigger LANGUAGE plpgsql AS $$
DECLARE
    obj record;
BEGIN
    FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
    LOOP
        RAISE NOTICE '% dropped object: % %.% %',
                     tg_tag,
                     obj.object_type,
                     obj.schema_name,
                     obj.object_name,
                     obj.object_identity;
    END LOOP;
END
$$;

CREATE EVENT TRIGGER test_event_trigger_for_drops
   ON sql_drop
   EXECUTE PROCEDURE test_event_trigger_for_drops();

postgres=# DROP TABLE obce CASCADE;
NOTICE:  drop cascades to materialized view obce_stredocesky_kraj
NOTICE:  DROP TABLE dropped object: table public.obce public.obce
NOTICE:  DROP TABLE dropped object: index public.obce_okres_id_idx public.obce_okres_id_idx
NOTICE:  DROP TABLE dropped object: table constraint public.<NULL> obce_okres_id_fk on public.obce
NOTICE:  DROP TABLE dropped object: trigger <NULL>.<NULL>  "RI_ConstraintTrigger_a_46471" on public.okresy
NOTICE:  DROP TABLE dropped object: trigger <NULL>.<NULL> "RI_ConstraintTrigger_a_46472" on public.okresy
NOTICE:  DROP TABLE dropped object: trigger <NULL>.<NULL> "RI_ConstraintTrigger_c_46473" on public.obce
NOTICE:  DROP TABLE dropped object: trigger <NULL>.<NULL> "RI_ConstraintTrigger_c_46474" on public.obce
NOTICE:  DROP TABLE dropped object: sequence public.obce_id_seq public.obce_id_seq
NOTICE:  DROP TABLE dropped object: type public.obce_id_seq public.obce_id_seq
NOTICE:  DROP TABLE dropped object: default value <NULL>.<NULL> for public.obce.id
NOTICE:  DROP TABLE dropped object: table constraint public.<NULL> _obce_pkey on public.obce
NOTICE:  DROP TABLE dropped object: index public._obce_pkey public._obce_pkey
NOTICE:  DROP TABLE dropped object: materialized view public.obce_stredocesky_kraj public.obce_stredocesky_kraj
NOTICE:  DROP TABLE dropped object: index public.obce_stredocesky_kraj_nazev_idx public.obce_stredocesky_kraj_nazev_idx
NOTICE:  DROP TABLE dropped object: type public.obce_stredocesky_kraj public.obce_stredocesky_kraj
NOTICE:  DROP TABLE dropped object: type public._obce_stredocesky_kraj public.obce_stredocesky_kraj[]
NOTICE:  DROP TABLE dropped object: rule <NULL>.<NULL> "_RETURN" on public.obce_stredocesky_kraj
NOTICE:  DROP TABLE dropped object: type public.obce public.obce
NOTICE:  DROP TABLE dropped object: type public._obce public.obce[]
DROP TABLE