我在PostgreSQL 11.10中创建了一个函数来处理DDL更改,并将其应用到订阅服务器中。以下是功能:
CREATE OR REPLACE FUNCTION public.intercept_ddl()
RETURNS event_trigger
LANGUAGE plpgsql
AS $function$
declare _qry text;
BEGIN
if (tg_tag='CREATE TABLE' or tg_tag='ALTER TABLE' or tg_tag='DROP TABLE') then
SELECT current_query() into _qry;
PERFORM pglogical.replicate_ddl_command('_qry', '{default}'), _qry;
end if;
END;
$function$
;
当我尝试它时,它抛出了一个错误:
错误:" _qry“行1或附近的语法错误:选择pglogical.replicate_ddl_command('_qry','{default}') ^ QUERY:选择pglogical.replicate_ddl_command('_qry','{default}')上下文:在执行排队SQL语句时:执行_qry PL/pgSQL函数intercept_ddl()第6行
如何传递_qry
变量以便我们可以使用它replicate_ddl_command()
?
按照Laurenz的指示修复单引号之后,我再次尝试使用以下命令:
alter table test alter COLUMN description type text;
并得到另一条错误消息:
错误:无法删除活动门户"pglogical“上下文:在执行排队的SQL语句期间: alter测试alter列描述类型text;SQL语句"SELECT pglogical.replicate_ddl_command( _qry,'{default}')”PL/pgSQL函数intercept_ddl()在执行时第7行
发布于 2021-03-10 22:59:40
除了按照Laurenz的指示修正单引号外,您可能还必须使用(默认的!)复制为命令'{ddl_sql}'
设置replicate_ddl_command()
。错误信息
无法删除活动门户"pglogical“
指示具有准备语句的打开门户,该语句将与DDL命令冲突。
CREATE OR REPLACE FUNCTION public.intercept_ddl()
RETURNS event_trigger
LANGUAGE plpgsql AS
$func$
BEGIN
PERFORM pglogical.replicate_ddl_command(current_query(), '{ddl_sql}'); -- !!
END
$func$;
您没有公开实际的事件触发器,但可能如下所示
CREATE EVENT TRIGGER foo
ON ddl_command_start
WHEN TAG IN ('CREATE TABLE', 'ALTER TABLE', 'DROP TABLE')
EXECUTE FUNCTION public.intercept_ddl();
在触发器本身中筛选命令标记,从而避免了函数中这样做的需要。这是更有效的,因为函数的调用只适用于适用的标记开始。
引用逻辑手册:
已有的三个复制集名为“default”、“default_insert_only”和“ddl_sql”。定义“ddl_sql”复制集是为了复制
pglogical.replicate_ddl_command
指定的模式更改。
和:
pglogical.replicate_ddl_command(command text, replication_sets text[])
在本地执行,然后将指定的命令发送到复制队列,以便在订阅指定replication_sets.Parameters:之一的订阅服务器上执行。replication_sets
-此命令应该与其关联的复制集数组默认为“{ddl_sql}”。发布于 2021-03-10 09:35:47
单引号中使用_qry
作为字符串常量,构成非法的SQL语句。此外,奇怪的附录, _qry
是语法上的无稽之谈。
试一试
PERFORM pglogical.replicate_ddl_command(_qry, '{default}');
然后,_qry
将被识别为变量引用。
https://dba.stackexchange.com/questions/286788
复制相似问题