我是 Postgresql 的新手,我正在研究它的功能。带有条件“什么都不做”的更新/删除规则似乎打破了每个更新/删除查询的“返回子句”。从 postgresql 9.5 起有什么解决方案吗?
这是我为测试而运行的简单 sql 片段:
-- clear && dropdb --if-exists graph && createdb graph -E UTF8 -T template0 && psql graph < schema.sql
create table vertices (
id bigserial not null primary key,
hash char(32),
label varchar(128) not null,
data jsonb default '{}'
);
-- default groups and users cannot be updated or deleted --
create or replace rule preventDefaultVtxUpdate as
on update to vertices
where ( old.label in ('group', 'user') and old.data->>'name' in ('superadmin', 'guest') )
do instead nothing;
create or replace rule preventDefaultVtxDelete as
on delete to vertices
where ( old.label in ('group', 'user') and old.data->>'name' in ('superadmin', 'guest') )
do instead nothing;
-- default groups and users
insert into vertices (label, data) values ('group', '{"name":"superadmin"}');
insert into vertices (label, data) values ('group', '{"name":"guest"}');
insert into vertices (label, data) values ('user', '{"name":"superadmin"}');
insert into vertices (label, data) values ('user', '{"name":"guest"}');
-- try
update vertices set data = '{}' returning *;
delete from vertices returning *;
它大喊:
ERROR: cannot perform UPDATE RETURNING on relation "vertices"
HINT: You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause.
ERROR: cannot perform DELETE RETURNING on relation "vertices"
HINT: You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause.
使用当前解决方案编辑:正如评论的那样,我解决了将规则重写为触发器的问题。它更丑但有效。使用以下触发器而不是规则对性能有何影响?
create table vertices (
id bigserial not null primary key,
hash char(32),
label varchar(128) not null,
data jsonb default '{}'
);
create or replace function preventDefaultVtxUpdateAndDelete() returns trigger AS $preventDefaultVtxUpdateAndDelete$
begin
return null;
end
$preventDefaultVtxUpdateAndDelete$ language plpgsql;
create trigger preventDefaultVtxUpdateAndDelete
before update or delete on vertices
for each row
when ( old.label in ('group', 'user') and old.data->>'name' in ('superadmin', 'guest') )
execute procedure preventDefaultVtxUpdateAndDelete();
-- default groups and users
insert into vertices (label, data) values ('group', '{"name":"superadmin"}');
insert into vertices (label, data) values ('group', '{"name":"guest"}');
insert into vertices (label, data) values ('user', '{"name":"superadmin"}');
insert into vertices (label, data) values ('user', '{"name":"guest"}');
insert into vertices (label, data) values ('user', '{"name":"ciao"}');
-- try
select * from vertices;
update vertices set data = '{}' returning *;
delete from vertices returning *;
select * from vertices;