From: Nathan Bossart <nathandbossart@gmail.com>
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: Nisha Moond <nisha.moond412@gmail.com>
Cc: Euler Taveira <euler@eulerto.com>
Cc: Michael Paquier <michael@paquier.xyz>
Cc: Amit Kapila <amit.kapila16@gmail.com>
Cc: Alexander Lakhin <exclusion@gmail.com>
Cc: Jonathan S. Katz <jkatz@postgresql.org>
Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Subject: Re: Large expressions in indexes can't be stored (non-TOASTable)
Date: Mon, 28 Apr 2025 16:51:07 -0500
Message-ID: <aA_4S5ZBaI_Qje2s@nathan> (raw)
In-Reply-To: <905635.1745876108@sss.pgh.pa.us>
References: <18a111db-9f31-449c-a14b-61779a69f344@app.fastmail.com>
<Z_mHvqVyGjEZhzl7@nathan>
<aAZqiKRhUv7-fSpQ@nathan>
<CABdArM6j03AAX5A2B9TPCZrY1xr+eFpGpzfdOBAww7mZnniUFg@mail.gmail.com>
<aAfP_bitjVC1bcNV@nathan>
<aAla1fg-1vPeXNck@nathan>
<1503201.1745444021@sss.pgh.pa.us>
<aAlfU06XTChyIGBD@nathan>
<aA_zMYasoUwNrDx1@nathan>
<905635.1745876108@sss.pgh.pa.us>
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
Attachments:v6-0001-Remove-pg_replication_origin-s-TOAST-table.patch (text/plain, 8.3K) download
From 39f870e69aa0cb08c0ef653b60ff07fa020c6bba Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathan@postgresql.org>
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 <michael@paquier.xyz>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Reviewed-by: Euler Taveira <euler@eulerto.com>
Reviewed-by: Nisha Moond <nisha.moond412@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
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.sgmlindex 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
<para>
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.
</para></entry>
</row>
diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.cindex 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.cindex 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.hindex 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.hindex 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.outindex 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.outindex 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.sqlindex 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.sqlindex 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)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: nathandbossart@gmail.com, tgl@sss.pgh.pa.us, nisha.moond412@gmail.com, euler@eulerto.com, michael@paquier.xyz, amit.kapila16@gmail.com, exclusion@gmail.com, jkatz@postgresql.org, pgsql-hackers@lists.postgresql.org
Subject: Re: Large expressions in indexes can't be stored (non-TOASTable)
In-Reply-To: <aA_4S5ZBaI_Qje2s@nathan>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox