我惊讶地发现 Postgres 如此依赖管理员的良好行为来防止对索引使用(“曾经”)的函数发生更改。我实际上认为这是非常有问题的。没有什么可以阻止错误的行为,我认为这是一个设计问题,而不是用户错误。
所以我决定制作一个方便的小系统来使用事件触发器(以及一点点正则表达式黑客)来执行这种强制。我认为它的保水性很好,但我还没有以任何高压方式对其进行测试。
使用这些:
CREATE OR REPLACE FUNCTION pg_index_monitor()
RETURNS event_trigger LANGUAGE plpgsql AS $$
DECLARE
obj record;
BEGIN
FOR obj IN (
WITH
index_functions AS
(
select
unnest(regexp_matches(indexprs, '(?<=(funcid(\s)))(\d+)', 'g'))::oid as objid
, indexrelid
FROM pg_index
WHERE
indexprs IS NOT NULL
)
SELECT
*
FROM pg_event_trigger_ddl_commands()
JOIN index_functions USING (objid)
JOIN pg_class ON indexrelid = oid
where
object_type = 'function'
)
LOOP
RAISE EXCEPTION 'This function cannot be modified as it is being used by index "%".', obj.relname;
END LOOP;
END
$$
;
DROP EVENT TRIGGER IF EXISTS pg_index_monitor_trigger;
CREATE EVENT TRIGGER pg_index_monitor_trigger
ON ddl_command_end
EXECUTE FUNCTION pg_index_monitor();
然后,如果我有一个依赖于正在更新的函数的索引(旧的或新的),它将引发错误。
CREATE INDEX some_index ON some_table (test(some_column));
然后尝试编辑该链接功能:
CREATE OR REPLACE FUNCTION test(text) RETURNS text AS $$
select 'abc'::text;
$$
LANGUAGE sql
IMMUTABLE
;
[P0001] ERROR: This function cannot be modified as it is being used by index "some_index".