What
NamedTuplestore
按字面意思理解,就是一个有名字的 tuplestore, 那估计就不是一个正常的表。根据 PostgreSQL 的官方叫法,NamedTuplestoreScan 对应的表称为为 Ephemeral Named Relation
, 中文翻译为 短暂的命名关系
.
When
在使用触发器的时候会使用到该特性
How
CREATE TABLE transition_table_base (id int PRIMARY KEY, val text);
CREATE FUNCTION transition_table_base_ins_func()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
t text;
l text;
BEGIN
t = '';
FOR l IN EXECUTE
$q$
EXPLAIN (TIMING off, COSTS off, VERBOSE on)
SELECT * FROM newtable
$q$ LOOP
t = t || l || E'\n';
END LOOP;
RAISE INFO '%', t;
RETURN new;
END;
$$;
-- `AFTER INSERT` and `STATEMENT` trigger
CREATE TRIGGER transition_table_base_ins_trig
AFTER INSERT ON transition_table_base
REFERENCING NEW TABLE AS newtable
FOR EACH STATEMENT
EXECUTE PROCEDURE transition_table_base_ins_func();
上面的 SQL 和 NamedTuplestore 关联的是 REFERENCING NEW TABLE AS newtable
. newtable
表在触发器函数中被使用。与之关联的还有 OLD TABLE as oldtable
, 但本例中使用的是 AFTER INSERT
, 因 PG 限制,不能使用。
可以通过下面这条 SQL 查看表关联的触发器,
select * from pg_trigger where tgrelid = 'transition_table_base'::regclass::oid \gx
对于其他触发器类型也是可以的,
-- 先删除已有的触发器
drop trigger transition_table_base_ins_trig on transition_table_base;
-- `AFTER UPDATE` and `FOR EACH ROW` trigger
CREATE TRIGGER transition_table_base_ins_trig_row
AFTER UPDATE ON transition_table_base
REFERENCING OLD TABLE AS oldtable NEW TABLE AS newtable
FOR EACH ROW
EXECUTE PROCEDURE transition_table_base_ins_func();
上面新的触发器就可以使用 REFERENCING OLD TABLE AS oldtable NEW TABLE AS newtable
.
Debug
可以将断点设置在 make_namedtuplestorescan
函数中判断是否会生成 NamedTuplestoreScan.