PostgreSQL suppress_redundant_updates_trigger 中的错误?

A bug in PostgreSQL suppress_redundant_updates_trigger?

我在 PostgreSQL 中研究一组触发器,我想我无意中发现了内置 function/trigger suppress_redundant_updates_trigger() 的错误。它在我的配置(笔记本电脑上的 PostgreSQL 12)上完全可重现。

首先我设置了一个 table,有两个“每行前”触发器:

CREATE TABLE test (id int, val text);
INSERT INTO test VALUES (1, 'one'), (2, 'two');

CREATE OR REPLACE FUNCTION am_i_touched() RETURNS trigger LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
    RAISE NOTICE 'Yes, I am touched!';
    RETURN NEW;
END;
$BODY$;

CREATE TRIGGER az_test_suppress_redundant_update
    BEFORE UPDATE ON public.test
    FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();

-- Make sure trigger name is after the previous one 
-- in alphabetical order as it drives execution order
CREATE TRIGGER bz_am_I_touched
    BEFORE UPDATE ON public.test 
    FOR EACH ROW EXECUTE PROCEDURE am_i_touched();

我然后运行UPDATE test SET id = 1 WHERE id = 1。正如预期的那样,更新被第一个触发器抑制,因为该行保持不变,并且 bz_am_i_touched() 永远不会触发。到目前为止一切顺利。

但后来我运行:

ALTER TABLE test ADD COLUMN newcol int

现在,我再次 运行 UPDATE test SET id = 1 WHERE id = 1...而这一次,更新未被抑制并且 bz_am_i_touched() 触发! PGAdmin (v4) 报告更新了一条记录,而不是像以前那样为零!

这是一次性事件。进一步 UPDATE test SET id = 1 WHERE id = 1 按预期工作...但后来我尝试了 UPDATE test SET id = 2 WHERE id = 2... 我再次遇到这种奇怪的行为 - 更新未被抑制。

这是预期的行为吗?我无法理解 UPDATE test SET id = 1 WHERE id = 1 如何导致更新不被抑制。

newcol NULL 值在新元组和旧元组之间的表示方式不同。所以他们不被认为是相同的,所以更新没有被抑制。

元组与 memcmp 的总数进行比较,因此即使 user-invisible 字节的差异也会很明显。它不会循环遍历每个字段,就哪些差异在语义上有意义做出单独的 type-dependent 决定。这似乎是故意的,为了速度和简单。我怀疑它会被认为是一个错误。