与 UPDATE 规则相比,postgres INSERT 规则中生成的 UUID 行为

Generated UUIDs behavior in postgres INSERT rule compared to the UPDATE rule

我有一个带有单个 table 的 postgres 数据库。这个 table 的主键是生成的 UUID。我正在尝试向该数据库添加一个日志记录 table,以便每当添加或删除一行时,日志记录 table 都会获得一个条目。我的 table 具有以下结构

CREATE TABLE configuration (
     id    uuid NOT NULL DEFAULT uuid_generate_v4(),
     name  text,
     data  json 
);

我的日志记录 table 具有以下结构

CREATE TABLE configuration_log (
    configuration_id         uuid,
    new_configuration_data   json,
    old_configuration_data   json,
    "user"                   text,
    time                     timestamp
);

我添加了以下规则:

CREATE OR REPLACE RULE log_configuration_insert AS ON INSERT TO "configuration"
       DO INSERT INTO configuration_log VALUES (
          NEW.id,
          NEW.data,
          '{}',
          current_user,
          current_timestamp
       );

CREATE OR REPLACE RULE log_configuration_update AS ON UPDATE TO "configuration"
      WHERE NEW.data::json::text != OLD.data::json::text
      DO INSERT INTO configuration_log VALUES (
          NEW.id,
          NEW.data,
          OLD.data,
          current_user,
          current_timestamp
      );

现在,如果我在配置 table 中插入一个值,配置 table 和 configuration_log table 中的 UUID 是不同的。例如,插入查询

INSERT INTO configuration (name, data) 
       VALUES ('test', '{"property1":"value1"}')

结果是this... the UUID is c2b6ca9b-1771-404d-baae-ae2ec69785ac in the configuration table whereas in the configuration_log table the result is this...UUID id 16109caa-dddc-4959-8054-0b9df6417406

但是,更新规则按预期工作。因此,如果我将更新查询写为

UPDATE "configuration" 
    SET "data" = '{"property1":"abcd"}' 
    WHERE "id" = 'c2b6ca9b-1771-404d-baae-ae2ec69785ac';

configuration_log table 得到正确的 UUID here 即 c2b6ca9b-1771-404d-baae-ae2ec69785ac

我在两个规则中都使用了 NEW.id,所以我期待相同的行为。谁能指出我在这里可能做错了什么?

谢谢

这是另一个很好的例子,为什么 rules should be avoided

Quote from the manual:

For any reference to NEW, the target list of the original query is searched for a corresponding entry. If found, that entry's expression replaces the reference.

所以 NEW.id 被替换为 uuid_generate_v4() 这解释了为什么您看到不同的值。

您应该将其重写为触发器。


顺便说一句:使用 jsonbjson 更可取,那么您还可以摆脱 json 列到 text 的(基本上不正确的)强制转换比较内容。