Skip to content

Commit ec47100

Browse files
committed
Ignore temporary relations in RelidByRelfilenumber()
Temporary relations may share the same RelFileNumber with a permanent relation, or other temporary relations associated with other sessions. Being able to uniquely identify a temporary relation would require RelidByRelfilenumber() to know about the proc number of the temporary relation it wants to identify, something it is not designed for since its introduction in f01d1ae. There are currently three callers of RelidByRelfilenumber(): - autoprewarm. - Logical decoding, reorder buffer. - pg_filenode_relation(), that attempts to find a relation OID based on a tablespace OID and a RelFileNumber. This makes the situation problematic particularly for the first two cases, leading to the possibility of random ERRORs due to inconsistencies that temporary relations can create in the cache maintained by RelidByRelfilenumber(). The third case should be less of an issue, as I suspect that there are few direct callers of pg_filenode_relation(). The window where the ERRORs are happen is very narrow, requiring an OID wraparound to create a lookup conflict in RelidByRelfilenumber() with a temporary table reusing the same OID as another relation already cached. The problem is easier to reach in workloads with a high OID consumption rate, especially with a higher number of temporary relations created. We could get pg_filenode_relation() and RelidByRelfilenumber() to work with temporary relations if provided the means to identify them with an optional proc number given in input, but the years have also shown that we do not have a use case for it, yet. Note that this could not be backpatched if pg_filenode_relation() needs changes. It is simpler to ignore temporary relations. Reported-by: Shenhao Wang <wangsh.fnst@fujitsu.com> Author: Vignesh C <vignesh21@gmail.com> Reviewed-By: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Reviewed-By: Robert Haas <robertmhaas@gmail.com> Reviewed-By: Kyotaro Horiguchi <horikyota.ntt@gmail.com> Reviewed-By: Takamichi Osumi <osumi.takamichi@fujitsu.com> Reviewed-By: Michael Paquier <michael@paquier.xyz> Reviewed-By: Masahiko Sawada <sawada.mshk@gmail.com> Reported-By: Shenhao Wang <wangsh.fnst@fujitsu.com> Discussion: https://postgr.es/m/bbaaf9f9-ebb2-645f-54bb-34d6efc7ac42@fujitsu.com Backpatch-through: 13
1 parent 1c58a1b commit ec47100

File tree

7 files changed

+41
-4
lines changed

7 files changed

+41
-4
lines changed

doc/src/sgml/func.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27116,7 +27116,8 @@ postgres=# SELECT * FROM pg_walfile_name_offset((pg_backup_stop()).lsn);
2711627116
<function>pg_relation_filepath</function>. For a relation in the
2711727117
database's default tablespace, the tablespace can be specified as zero.
2711827118
Returns <literal>NULL</literal> if no relation in the current database
27119-
is associated with the given values.
27119+
is associated with the given values, or if dealing with a temporary
27120+
relation.
2712027121
</para></entry>
2712127122
</row>
2712227123
</tbody>

src/backend/utils/adt/dbsize.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,9 @@ pg_relation_filenode(PG_FUNCTION_ARGS)
895895
*
896896
* We don't fail but return NULL if we cannot find a mapping.
897897
*
898+
* Temporary relations are not detected, returning NULL (see
899+
* RelidByRelfilenumber() for the reasons).
900+
*
898901
* InvalidOid can be passed instead of the current database's default
899902
* tablespace.
900903
*/

src/backend/utils/cache/relfilenodemap.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ InitializeRelfilenodeMap(void)
132132
* Map a relation's (tablespace, filenode) to a relation's oid and cache the
133133
* result.
134134
*
135+
* A temporary relation may share its relfilenumber with a permanent relation
136+
* or temporary relations created in other backends. Being able to uniquely
137+
* identify a temporary relation would require a backend's proc number, which
138+
* we do not know about. Hence, this function ignores this case.
139+
*
135140
* Returns InvalidOid if no relation matching the criteria could be found.
136141
*/
137142
Oid
@@ -211,6 +216,9 @@ RelidByRelfilenode(Oid reltablespace, Oid relfilenode)
211216
{
212217
Form_pg_class classform = (Form_pg_class) GETSTRUCT(ntp);
213218

219+
if (classform->relpersistence == RELPERSISTENCE_TEMP)
220+
continue;
221+
214222
if (found)
215223
elog(ERROR,
216224
"unexpected duplicate for tablespace %u, relfilenode %u",

src/test/regress/expected/alter_table.out

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3458,12 +3458,15 @@ SELECT conname as constraint, obj_description(oid, 'pg_constraint') as comment F
34583458
-- filenode function call can return NULL for a relation dropped concurrently
34593459
-- with the call's surrounding query, so ignore a NULL mapped_oid for
34603460
-- relations that no longer exist after all calls finish.
3461+
-- Temporary relations are ignored, as not supported by pg_filenode_relation().
34613462
CREATE TEMP TABLE filenode_mapping AS
34623463
SELECT
34633464
oid, mapped_oid, reltablespace, relfilenode, relname
34643465
FROM pg_class,
34653466
pg_filenode_relation(reltablespace, pg_relation_filenode(oid)) AS mapped_oid
3466-
WHERE relkind IN ('r', 'i', 'S', 't', 'm') AND mapped_oid IS DISTINCT FROM oid;
3467+
WHERE relkind IN ('r', 'i', 'S', 't', 'm')
3468+
AND relpersistence != 't'
3469+
AND mapped_oid IS DISTINCT FROM oid;
34673470
SELECT m.* FROM filenode_mapping m LEFT JOIN pg_class c ON c.oid = m.oid
34683471
WHERE c.oid IS NOT NULL OR m.mapped_oid IS NOT NULL;
34693472
oid | mapped_oid | reltablespace | relfilenode | relname

src/test/regress/expected/create_table.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ ERROR: tables declared WITH OIDS are not supported
9292
-- but explicitly not adding oids is still supported
9393
CREATE TEMP TABLE withoutoid() WITHOUT OIDS; DROP TABLE withoutoid;
9494
CREATE TEMP TABLE withoutoid() WITH (oids = false); DROP TABLE withoutoid;
95+
-- temporary tables are ignored by pg_filenode_relation().
96+
CREATE TEMP TABLE relation_filenode_check(c1 int);
97+
SELECT relpersistence,
98+
pg_filenode_relation (reltablespace, pg_relation_filenode(oid))
99+
FROM pg_class
100+
WHERE relname = 'relation_filenode_check';
101+
relpersistence | pg_filenode_relation
102+
----------------+----------------------
103+
t |
104+
(1 row)
105+
106+
DROP TABLE relation_filenode_check;
95107
-- check restriction with default expressions
96108
-- invalid use of column reference in default expressions
97109
CREATE TABLE default_expr_column (id int DEFAULT (id));

src/test/regress/sql/alter_table.sql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,13 +2176,15 @@ SELECT conname as constraint, obj_description(oid, 'pg_constraint') as comment F
21762176
-- filenode function call can return NULL for a relation dropped concurrently
21772177
-- with the call's surrounding query, so ignore a NULL mapped_oid for
21782178
-- relations that no longer exist after all calls finish.
2179+
-- Temporary relations are ignored, as not supported by pg_filenode_relation().
21792180
CREATE TEMP TABLE filenode_mapping AS
21802181
SELECT
21812182
oid, mapped_oid, reltablespace, relfilenode, relname
21822183
FROM pg_class,
21832184
pg_filenode_relation(reltablespace, pg_relation_filenode(oid)) AS mapped_oid
2184-
WHERE relkind IN ('r', 'i', 'S', 't', 'm') AND mapped_oid IS DISTINCT FROM oid;
2185-
2185+
WHERE relkind IN ('r', 'i', 'S', 't', 'm')
2186+
AND relpersistence != 't'
2187+
AND mapped_oid IS DISTINCT FROM oid;
21862188
SELECT m.* FROM filenode_mapping m LEFT JOIN pg_class c ON c.oid = m.oid
21872189
WHERE c.oid IS NOT NULL OR m.mapped_oid IS NOT NULL;
21882190

src/test/regress/sql/create_table.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ CREATE TABLE withoid() WITH (oids = true);
6262
CREATE TEMP TABLE withoutoid() WITHOUT OIDS; DROP TABLE withoutoid;
6363
CREATE TEMP TABLE withoutoid() WITH (oids = false); DROP TABLE withoutoid;
6464

65+
-- temporary tables are ignored by pg_filenode_relation().
66+
CREATE TEMP TABLE relation_filenode_check(c1 int);
67+
SELECT relpersistence,
68+
pg_filenode_relation (reltablespace, pg_relation_filenode(oid))
69+
FROM pg_class
70+
WHERE relname = 'relation_filenode_check';
71+
DROP TABLE relation_filenode_check;
72+
6573
-- check restriction with default expressions
6674
-- invalid use of column reference in default expressions
6775
CREATE TABLE default_expr_column (id int DEFAULT (id));

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy