v3_RelidByRelfilenumber_prefer_perm_rels_master.patch
text/x-patch
Filename: v3_RelidByRelfilenumber_prefer_perm_rels_master.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v3
| File | + | − |
|---|---|---|
| doc/src/sgml/func.sgml | 10 | 6 |
| src/backend/utils/cache/relfilenumbermap.c | 14 | 3 |
| src/test/regress/expected/alter_table.out | 2 | 2 |
| src/test/regress/expected/create_table.out | 10 | 0 |
| src/test/regress/sql/alter_table.sql | 2 | 2 |
| src/test/regress/sql/create_table.sql | 6 | 0 |
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 6fa1d6586b8..4f6edf308b5 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -30198,16 +30198,20 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
<indexterm>
<primary>pg_filenode_relation</primary>
</indexterm>
- <function>pg_filenode_relation</function> ( <parameter>tablespace</parameter> <type>oid</type>, <parameter>filenode</parameter> <type>oid</type> )
+ <function>pg_filenode_relation</function>
+ ( <parameter>tablespace</parameter> <type>oid</type>,
+ <parameter>filenode</parameter> <type>oid</type>)
<returnvalue>regclass</returnvalue>
</para>
<para>
Returns a relation's OID given the tablespace OID and filenode it is
- stored under. This is essentially the inverse mapping of
- <function>pg_relation_filepath</function>. For a relation in the
- database's default tablespace, the tablespace can be specified as zero.
- Returns <literal>NULL</literal> if no relation in the current database
- is associated with the given values.
+ stored under, if the given values match a permanent relation. This is
+ essentially the inverse mapping
+ of <function>pg_relation_filepath</function> only regarding permanent
+ relations. For a relation in the database's default tablespace, the
+ tablespace can be specified as zero. Returns <literal>NULL</literal>
+ if no permanent relation in the current database is associated with
+ the given values.
</para></entry>
</row>
</tbody>
diff --git a/src/backend/utils/cache/relfilenumbermap.c b/src/backend/utils/cache/relfilenumbermap.c
index 8a2f6f8c693..6ffddfe0c5e 100644
--- a/src/backend/utils/cache/relfilenumbermap.c
+++ b/src/backend/utils/cache/relfilenumbermap.c
@@ -127,10 +127,11 @@ InitializeRelfilenumberMap(void)
}
/*
- * Map a relation's (tablespace, relfilenumber) to a relation's oid and cache
- * the result.
+ * Map a relation's (tablespace, relfilenumber) to a permanent relation's oid
+ * and cache the result.
*
- * Returns InvalidOid if no relation matching the criteria could be found.
+ * Returns InvalidOid if no permanent relation matching the criteria could be
+ * found.
*/
Oid
RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber)
@@ -208,6 +209,16 @@ RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber)
{
Form_pg_class classform = (Form_pg_class) GETSTRUCT(ntp);
+ /*
+ * Temporary relations should be excluded. This exclusion is
+ * necessary because they can lead to the wrong result; the
+ * relfilenumber space is shared with persistent
+ * relations. Additionally, excluding them is possible since they
+ * are not the focus in this context.
+ */
+ if (classform->relpersistence == RELPERSISTENCE_TEMP)
+ continue;
+
if (found)
elog(ERROR,
"unexpected duplicate for tablespace %u, relfilenumber %u",
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 362f38856d2..9c97d38bb1b 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -3501,9 +3501,9 @@ SELECT
oid, mapped_oid, reltablespace, relfilenode, relname
FROM pg_class,
pg_filenode_relation(reltablespace, pg_relation_filenode(oid)) AS mapped_oid
-WHERE relkind IN ('r', 'i', 'S', 't', 'm') AND mapped_oid IS DISTINCT FROM oid;
+WHERE relkind IN ('r', 'i', 'S', 'm') AND mapped_oid IS DISTINCT FROM oid;
SELECT m.* FROM filenode_mapping m LEFT JOIN pg_class c ON c.oid = m.oid
-WHERE c.oid IS NOT NULL OR m.mapped_oid IS NOT NULL;
+WHERE (c.oid IS NOT NULL OR m.mapped_oid IS NOT NULL) AND c.relpersistence != 't';
oid | mapped_oid | reltablespace | relfilenode | relname
-----+------------+---------------+-------------+---------
(0 rows)
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index 76604705a93..b6e5083ee6b 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -102,6 +102,16 @@ ERROR: tables declared WITH OIDS are not supported
-- but explicitly not adding oids is still supported
CREATE TEMP TABLE withoutoid() WITHOUT OIDS; DROP TABLE withoutoid;
CREATE TEMP TABLE withoutoid() WITH (oids = false); DROP TABLE withoutoid;
+-- verify that temporary tables data are not retrieved by pg_filenode_relation
+CREATE TEMP TABLE filenoderelationcheck(c1 int);
+SELECT pg_filenode_relation (reltablespace, pg_relation_filenode(oid)) FROM pg_class
+WHERE relname = 'filenoderelationcheck';
+ pg_filenode_relation
+----------------------
+
+(1 row)
+
+DROP TABLE filenoderelationcheck;
-- check restriction with default expressions
-- invalid use of column reference in default expressions
CREATE TABLE default_expr_column (id int DEFAULT (id));
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 84e93ef575e..20d50a3a214 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -2191,10 +2191,10 @@ SELECT
oid, mapped_oid, reltablespace, relfilenode, relname
FROM pg_class,
pg_filenode_relation(reltablespace, pg_relation_filenode(oid)) AS mapped_oid
-WHERE relkind IN ('r', 'i', 'S', 't', 'm') AND mapped_oid IS DISTINCT FROM oid;
+WHERE relkind IN ('r', 'i', 'S', 'm') AND mapped_oid IS DISTINCT FROM oid;
SELECT m.* FROM filenode_mapping m LEFT JOIN pg_class c ON c.oid = m.oid
-WHERE c.oid IS NOT NULL OR m.mapped_oid IS NOT NULL;
+WHERE (c.oid IS NOT NULL OR m.mapped_oid IS NOT NULL) AND c.relpersistence != 't';
-- Checks on creating and manipulation of user defined relations in
-- pg_catalog.
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index 37a227148e9..44b0c14902f 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -68,6 +68,12 @@ CREATE TABLE withoid() WITH (oids = true);
CREATE TEMP TABLE withoutoid() WITHOUT OIDS; DROP TABLE withoutoid;
CREATE TEMP TABLE withoutoid() WITH (oids = false); DROP TABLE withoutoid;
+-- verify that temporary tables data are not retrieved by pg_filenode_relation
+CREATE TEMP TABLE filenoderelationcheck(c1 int);
+SELECT pg_filenode_relation (reltablespace, pg_relation_filenode(oid)) FROM pg_class
+WHERE relname = 'filenoderelationcheck';
+DROP TABLE filenoderelationcheck;
+
-- check restriction with default expressions
-- invalid use of column reference in default expressions
CREATE TABLE default_expr_column (id int DEFAULT (id));