Hello! The patch was rebased on current master. And here is a simplified crash reproduction: 1) On primary with 'wal_level = logical' execute: CREATE TABLE public.test (id int NOT NULL, val integer); CREATE PUBLICATION test_pub FOR TABLE test;
2) On replica replace XXXX in the repcmd.sql attached with primary port and execute it: psql -f repcmd.sql 3) On master execute command: INSERT INTO test VALUES ('1'); With best regards, -- Anton A. Melnikov Postgres Professional: http://www.postgrespro.com The Russian Postgres Company
commit 4de66e1b1ffaeaacdd72f3e72789ca05b114476b Author: Anton A. Melnikov <a.melni...@postgrespro.ru> Date: Sun Aug 21 18:27:44 2022 +0300 Fix logical replica crash if there was an error in a function. diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index a9fe45e347..1381fae575 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -1007,8 +1007,9 @@ sql_function_parse_error_callback(void *arg) * anonymous-block handler, not only for SQL-language functions. * It is assumed that the syntax error position is initially relative to the * function body string (as passed in). If possible, we adjust the position - * to reference the original command text; if we can't manage that, we set - * up an "internal query" syntax error instead. + * to reference the original command text; if we can't manage that or + * can't get the original command text when ActivePortal is not defined, + * we set up an "internal query" syntax error instead. * * Returns true if a syntax error was processed, false if not. */ @@ -1016,7 +1017,7 @@ bool function_parse_error_transpose(const char *prosrc) { int origerrposition; - int newerrposition; + int newerrposition = 0; const char *queryText; /* @@ -1034,12 +1035,15 @@ function_parse_error_transpose(const char *prosrc) return false; } - /* We can get the original query text from the active portal (hack...) */ - Assert(ActivePortal && ActivePortal->status == PORTAL_ACTIVE); - queryText = ActivePortal->sourceText; + if (ActivePortal) + { + /* We can get the original query text from the active portal (hack...) */ + Assert(ActivePortal->status == PORTAL_ACTIVE); + queryText = ActivePortal->sourceText; - /* Try to locate the prosrc in the original text */ - newerrposition = match_prosrc_to_query(prosrc, queryText, origerrposition); + /* Try to locate the prosrc in the original text */ + newerrposition = match_prosrc_to_query(prosrc, queryText, origerrposition); + } if (newerrposition > 0) { @@ -1052,7 +1056,8 @@ function_parse_error_transpose(const char *prosrc) else { /* - * If unsuccessful, convert the position to an internal position + * If unsuccessful or ActivePortal not defined and original command + * text is unreachable, convert the position to an internal position * marker and give the function text as the internal query. */ errposition(0);
repcmd.sql
Description: application/sql