Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1u9WOe-002od7-S6 for pgsql-hackers@arkaria.postgresql.org; Mon, 28 Apr 2025 21:52:17 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1u9WNd-003W3I-OC for pgsql-hackers@arkaria.postgresql.org; Mon, 28 Apr 2025 21:51:14 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1u9WNd-003W3A-DW for pgsql-hackers@lists.postgresql.org; Mon, 28 Apr 2025 21:51:14 +0000 Received: from mail-il1-x129.google.com ([2607:f8b0:4864:20::129]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1u9WNc-0004iG-0Y for pgsql-hackers@lists.postgresql.org; Mon, 28 Apr 2025 21:51:14 +0000 Received: by mail-il1-x129.google.com with SMTP id e9e14a558f8ab-3d5e68418b5so52078945ab.2 for ; Mon, 28 Apr 2025 14:51:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745877070; x=1746481870; darn=lists.postgresql.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=kgc63E0aAZ6mbo/7KM4Uvy/blk54YDsUMD4W90ItJfc=; b=FQSTRkp8jIUkaENNVa/shG68zT3CGZP0y1+bRIkn5mzRtgS5KG+FhDWtCBfsn9zE92 nSnE4UqPlgKICwJjkbjFpjNfqje8QlAPiwro3XzhMr71cFfkNOi2ONL71jBn2l4zDjVn R9fG+sTvofJmZsRv4RjxtYyXpFwx9VZT2gNVc0XTzAWDLTPmXLlMQRHtPGiPdfTDvhmi zL8SEpYUdu6jehwEIYiDk/qH363v7/hwJ5x4Z5crNboXYADrLOWo1nI25+/uEcs28PU/ +7PG9sXyoLDd/nA28Pthf0trVKkm8BRyW+VjXHNZYiepoFMc5cY7QjfvRDc8wvaA9AnJ 8YTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745877070; x=1746481870; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=kgc63E0aAZ6mbo/7KM4Uvy/blk54YDsUMD4W90ItJfc=; b=Ytj6TZhZx8X0icQ19TXPIz/TCP7RpqcrvIX016GM0czKReuxljFzgF5zgOel7WWSkf qaQoaRxckETQuQFpxFfc+3hAIh17xMbM2zVUfxZ76/5QF5galqGK2Mxsr2Oi1INV3r1P ympoyztmZTwu/ZQw4lCgkFqa1GjNkcoSXURxHw/4WUkzt0/QyeyzVCYhOYxQpZJXDtWD agcAqS+LyKWC+v8uht/KfbG4qUUGAt6SqKibGPS4/SjyTmmBw/mQuirrVbvlMlJ0BDTU n6jvaZbSuV+tKy2q54clKCaW2kVXAIC2WQ49sgFe16g/PSpy7VT4PoBYMrizJYrVexA5 KwGw== X-Forwarded-Encrypted: i=1; AJvYcCU+igzzf3//xdmGnq/BZ19BoUTqOJE55vLWMMMbMXrr0wwNG1QE4JPlnlqPBWBLMgll1Ti6I1N2+hsW9i6G@lists.postgresql.org X-Gm-Message-State: AOJu0YxffSp+gAwYr76LLYNNId7A3ytslYg4I4JYfwgd/1fjFrK/RZqR DIlkERWALyNwiX3eWdcAYZ3Rf7rGT+8+deP+uaGo3Eh7E8UnEZvA X-Gm-Gg: ASbGnctcAWzvaJW6wQ8w09wM4k6jXwCsyaB00Pq3jloPnaTf+kEQKWufV3hIQsV3Kns pIyYprwQ+sOCS+SLlE+F+YtDpuDjpoUvzbNoeMXlBtaE2c/FpH+dXRkyXAXs5LgQ4P71T35yc/g hdqfwPatQoR/lDnIxvXj32aImMRMPN1T6XzXjeGzu9XzSJPSeb7T36KL89KNXjp7mQ2TRYYhowB RegHBw/c2wD/eA9L7cFKOn/t2FTIkyL9QFbmehA6dp3p8T3e4lZoC3xybkyL+2lbOqun6pEwTxi FSz2YqODrJo462DVyzIpcmMnyuRYiT/5s2y3qLHH0wMakAcjYcijfFkzrr1fMFEGIPg+TnMa8oM xXkYXNUbloC2qxWnARUfxX9J/SMKUWq8= X-Google-Smtp-Source: AGHT+IF0ObRmsf1HWoR7xb/lY0phOzuLjRfXQWENHRfrezArkSCclz6aSRcTkibgMQndNpP/Tflo4w== X-Received: by 2002:a05:6e02:1a68:b0:3d9:3adb:e589 with SMTP id e9e14a558f8ab-3d95df2092emr6427665ab.4.1745877069656; Mon, 28 Apr 2025 14:51:09 -0700 (PDT) Received: from nathan (162-195-168-172.lightspeed.stlsmo.sbcglobal.net. [162.195.168.172]) by smtp.gmail.com with ESMTPSA id 8926c6da1cb9f-4f862e0fd10sm12013173.18.2025.04.28.14.51.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Apr 2025 14:51:08 -0700 (PDT) Date: Mon, 28 Apr 2025 16:51:07 -0500 From: Nathan Bossart To: Tom Lane Cc: Nisha Moond , Euler Taveira , Michael Paquier , Amit Kapila , Alexander Lakhin , "Jonathan S. Katz" , PostgreSQL Hackers Subject: Re: Large expressions in indexes can't be stored (non-TOASTable) Message-ID: References: <18a111db-9f31-449c-a14b-61779a69f344@app.fastmail.com> <1503201.1745444021@sss.pgh.pa.us> <905635.1745876108@sss.pgh.pa.us> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="ISMl1f1T7/wWmeDc" Content-Disposition: inline In-Reply-To: <905635.1745876108@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --ISMl1f1T7/wWmeDc Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Mon, Apr 28, 2025 at 05:35:08PM -0400, Tom Lane wrote: > Possibly better idea: can we add something like > Assert(!OidIsValid(reltoastrelid)) in the code that is making this > assumption? Yeah, we could add something like that to replorigin_create() pretty easily. The comment for that would be even harder to miss. -- nathan --ISMl1f1T7/wWmeDc Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="v6-0001-Remove-pg_replication_origin-s-TOAST-table.patch" From 39f870e69aa0cb08c0ef653b60ff07fa020c6bba Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Mon, 28 Apr 2025 16:27:33 -0500 Subject: [PATCH v6 1/1] Remove pg_replication_origin's TOAST table. Reviewed-by: Michael Paquier Reviewed-by: Amit Kapila Reviewed-by: Euler Taveira Reviewed-by: Nisha Moond Reviewed-by: Tom Lane Discussion: https://postgr.es/m/ZvMSUPOqUU-VNADN%40nathan --- doc/src/sgml/func.sgml | 1 + src/backend/catalog/catalog.c | 2 -- src/backend/replication/logical/origin.c | 22 ++++++++++++++++++++ src/include/catalog/pg_replication_origin.h | 2 -- src/include/replication/origin.h | 7 +++++++ src/test/regress/expected/misc_functions.out | 4 ++++ src/test/regress/expected/misc_sanity.out | 7 ++++++- src/test/regress/sql/misc_functions.sql | 3 +++ src/test/regress/sql/misc_sanity.sql | 4 ++++ 9 files changed, 47 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 574a544d9fa..593e45495be 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -29941,6 +29941,7 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset Creates a replication origin with the given external name, and returns the internal ID assigned to it. + The name must be no longer than 512 bytes. diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index 60000bd0bc7..59caae8f1bc 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -346,8 +346,6 @@ IsSharedRelation(Oid relationId) relationId == PgDbRoleSettingToastIndex || relationId == PgParameterAclToastTable || relationId == PgParameterAclToastIndex || - relationId == PgReplicationOriginToastTable || - relationId == PgReplicationOriginToastIndex || relationId == PgShdescriptionToastTable || relationId == PgShdescriptionToastIndex || relationId == PgShseclabelToastTable || diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 6583dd497da..bd827bc6ed0 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -287,6 +287,16 @@ replorigin_create(const char *roname) rel = table_open(ReplicationOriginRelationId, ExclusiveLock); + /* + * We want to be able to access pg_replication_origin without setting up a + * snapshot. As of this writing, its TOAST table would only be used for + * replication origin names, which we avoid with a reasonable length + * restriction. If you add a TOAST table to this catalog, be sure to set + * up a snapshot everywhere it might be needed. For more information, see + * https://postgr.es/m/ZvMSUPOqUU-VNADN%40nathan. + */ + Assert(!OidIsValid(rel->rd_rel->reltoastrelid)); + for (roident = InvalidOid + 1; roident < PG_UINT16_MAX; roident++) { bool nulls[Natts_pg_replication_origin]; @@ -1296,6 +1306,18 @@ pg_replication_origin_create(PG_FUNCTION_ARGS) elog(WARNING, "replication origins created by regression test cases should have names starting with \"regress_\""); #endif + /* + * To avoid needing a TOAST table for pg_replication_origin, we restrict + * replication origin names to 512 bytes. This should be more than enough + * for all practical use. + */ + if (strlen(name) > MAX_RONAME_LEN) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("replication origin name is too long"), + errdetail("Replication origin names must be no longer than %d bytes.", + MAX_RONAME_LEN))); + roident = replorigin_create(name); pfree(name); diff --git a/src/include/catalog/pg_replication_origin.h b/src/include/catalog/pg_replication_origin.h index deb43065fe9..7ade8bbda39 100644 --- a/src/include/catalog/pg_replication_origin.h +++ b/src/include/catalog/pg_replication_origin.h @@ -54,8 +54,6 @@ CATALOG(pg_replication_origin,6000,ReplicationOriginRelationId) BKI_SHARED_RELAT typedef FormData_pg_replication_origin *Form_pg_replication_origin; -DECLARE_TOAST_WITH_MACRO(pg_replication_origin, 4181, 4182, PgReplicationOriginToastTable, PgReplicationOriginToastIndex); - DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops)); DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops)); diff --git a/src/include/replication/origin.h b/src/include/replication/origin.h index 9cb2248fa9f..29724c0dcae 100644 --- a/src/include/replication/origin.h +++ b/src/include/replication/origin.h @@ -33,6 +33,13 @@ typedef struct xl_replorigin_drop #define InvalidRepOriginId 0 #define DoNotReplicateId PG_UINT16_MAX +/* + * To avoid needing a TOAST table for pg_replication_origin, we restrict + * replication origin names to 512 bytes. This should be more than enough for + * all practical use. + */ +#define MAX_RONAME_LEN 512 + extern PGDLLIMPORT RepOriginId replorigin_session_origin; extern PGDLLIMPORT XLogRecPtr replorigin_session_origin_lsn; extern PGDLLIMPORT TimestampTz replorigin_session_origin_timestamp; diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out index d3f5d16a672..3de32c3c7ef 100644 --- a/src/test/regress/expected/misc_functions.out +++ b/src/test/regress/expected/misc_functions.out @@ -914,3 +914,7 @@ SELECT test_relpath(); (1 row) +-- pg_replication_origin.roname length restriction +SELECT pg_replication_origin_create('regress_' || repeat('a', 505)); +ERROR: replication origin name is too long +DETAIL: Replication origin names must be no longer than 512 bytes. diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out index b032a3f4761..b0b76fe3d9a 100644 --- a/src/test/regress/expected/misc_sanity.out +++ b/src/test/regress/expected/misc_sanity.out @@ -42,6 +42,10 @@ WHERE refclassid = 0 OR refobjid = 0 OR -- as user data by pg_upgrade, which would cause failures. -- 3. pg_authid, since its toast table cannot be accessed when it would be -- needed, i.e., during authentication before we've selected a database. +-- 4. pg_replication_origin, since we want to be able to access that catalog +-- without setting up a snapshot. As of this writing, its toast table would +-- only be used for replication origin names, which we can avoid with a +-- reasonable length restriction. SELECT relname, attname, atttypid::regtype FROM pg_class c JOIN pg_attribute a ON c.oid = attrelid WHERE c.oid < 16384 AND @@ -61,7 +65,8 @@ ORDER BY 1, 2; pg_class | relpartbound | pg_node_tree pg_largeobject | data | bytea pg_largeobject_metadata | lomacl | aclitem[] -(10 rows) + pg_replication_origin | roname | text +(11 rows) -- system catalogs without primary keys -- diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql index aaebb298330..ea72a62dab7 100644 --- a/src/test/regress/sql/misc_functions.sql +++ b/src/test/regress/sql/misc_functions.sql @@ -411,3 +411,6 @@ CREATE FUNCTION test_relpath() AS :'regresslib' LANGUAGE C; SELECT test_relpath(); + +-- pg_replication_origin.roname length restriction +SELECT pg_replication_origin_create('regress_' || repeat('a', 505)); diff --git a/src/test/regress/sql/misc_sanity.sql b/src/test/regress/sql/misc_sanity.sql index 135793871b4..86c193a0c42 100644 --- a/src/test/regress/sql/misc_sanity.sql +++ b/src/test/regress/sql/misc_sanity.sql @@ -45,6 +45,10 @@ WHERE refclassid = 0 OR refobjid = 0 OR -- as user data by pg_upgrade, which would cause failures. -- 3. pg_authid, since its toast table cannot be accessed when it would be -- needed, i.e., during authentication before we've selected a database. +-- 4. pg_replication_origin, since we want to be able to access that catalog +-- without setting up a snapshot. As of this writing, its toast table would +-- only be used for replication origin names, which we can avoid with a +-- reasonable length restriction. SELECT relname, attname, atttypid::regtype FROM pg_class c JOIN pg_attribute a ON c.oid = attrelid -- 2.39.5 (Apple Git-154) --ISMl1f1T7/wWmeDc--