Don't create relfilenode for relations without storage
Some relation kinds had relfilenode set to some non-zero value, but apparently the actual files did not really exist because creation was prevented elsewhere. Get rid of the phony pg_class.relfilenode values. Catversion bumped, but only because the sanity_test check will fail if run in a system initdb'd with the previous version. Reviewed-by: Kyotaro HORIGUCHI, Michael Paquier Discussion: https://postgr.es/m/20181206215552.fm2ypuxq6nhpwjuc@alvherre.pgsql
This commit is contained in:
parent
df5be63763
commit
807ae415c5
@ -324,35 +324,25 @@ heap_create(const char *relname,
|
|||||||
get_namespace_name(relnamespace), relname),
|
get_namespace_name(relnamespace), relname),
|
||||||
errdetail("System catalog modifications are currently disallowed.")));
|
errdetail("System catalog modifications are currently disallowed.")));
|
||||||
|
|
||||||
/*
|
/* Handle reltablespace for specific relkinds. */
|
||||||
* Decide if we need storage or not, and handle a couple other special
|
|
||||||
* cases for particular relkinds.
|
|
||||||
*/
|
|
||||||
switch (relkind)
|
switch (relkind)
|
||||||
{
|
{
|
||||||
case RELKIND_VIEW:
|
case RELKIND_VIEW:
|
||||||
case RELKIND_COMPOSITE_TYPE:
|
case RELKIND_COMPOSITE_TYPE:
|
||||||
case RELKIND_FOREIGN_TABLE:
|
case RELKIND_FOREIGN_TABLE:
|
||||||
create_storage = false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force reltablespace to zero if the relation has no physical
|
* Force reltablespace to zero if the relation has no physical
|
||||||
* storage. This is mainly just for cleanliness' sake.
|
* storage. This is mainly just for cleanliness' sake.
|
||||||
|
*
|
||||||
|
* Partitioned tables and indexes don't have physical storage
|
||||||
|
* either, but we want to keep their tablespace settings so that
|
||||||
|
* their children can inherit it.
|
||||||
*/
|
*/
|
||||||
reltablespace = InvalidOid;
|
reltablespace = InvalidOid;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RELKIND_PARTITIONED_TABLE:
|
|
||||||
case RELKIND_PARTITIONED_INDEX:
|
|
||||||
/*
|
|
||||||
* For partitioned tables and indexes, preserve tablespace so that
|
|
||||||
* it's used as the tablespace for future partitions.
|
|
||||||
*/
|
|
||||||
create_storage = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RELKIND_SEQUENCE:
|
case RELKIND_SEQUENCE:
|
||||||
create_storage = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force reltablespace to zero for sequences, since we don't
|
* Force reltablespace to zero for sequences, since we don't
|
||||||
@ -361,19 +351,21 @@ heap_create(const char *relname,
|
|||||||
reltablespace = InvalidOid;
|
reltablespace = InvalidOid;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
create_storage = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unless otherwise requested, the physical ID (relfilenode) is initially
|
* Decide whether to create storage. If caller passed a valid relfilenode,
|
||||||
* the same as the logical ID (OID). When the caller did specify a
|
* storage is already created, so don't do it here. Also don't create it
|
||||||
* relfilenode, it already exists; do not attempt to create it.
|
* for relkinds without physical storage.
|
||||||
*/
|
*/
|
||||||
if (OidIsValid(relfilenode))
|
if (!RELKIND_HAS_STORAGE(relkind) || OidIsValid(relfilenode))
|
||||||
create_storage = false;
|
create_storage = false;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
create_storage = true;
|
||||||
relfilenode = relid;
|
relfilenode = relid;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Never allow a pg_class entry to explicitly specify the database's
|
* Never allow a pg_class entry to explicitly specify the database's
|
||||||
|
4
src/backend/utils/cache/relcache.c
vendored
4
src/backend/utils/cache/relcache.c
vendored
@ -1253,6 +1253,10 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
|
|||||||
static void
|
static void
|
||||||
RelationInitPhysicalAddr(Relation relation)
|
RelationInitPhysicalAddr(Relation relation)
|
||||||
{
|
{
|
||||||
|
/* these relations kinds never have storage */
|
||||||
|
if (!RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
|
||||||
|
return;
|
||||||
|
|
||||||
if (relation->rd_rel->reltablespace)
|
if (relation->rd_rel->reltablespace)
|
||||||
relation->rd_node.spcNode = relation->rd_rel->reltablespace;
|
relation->rd_node.spcNode = relation->rd_rel->reltablespace;
|
||||||
else
|
else
|
||||||
|
@ -53,6 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 201901031
|
#define CATALOG_VERSION_NO 201901041
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -450,13 +450,12 @@ typedef struct ViewOptions
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* RelationIsMapped
|
* RelationIsMapped
|
||||||
* True if the relation uses the relfilenode map.
|
* True if the relation uses the relfilenode map. Note multiple eval
|
||||||
*
|
* of argument!
|
||||||
* NB: this is only meaningful for relkinds that have storage, else it
|
|
||||||
* will misleadingly say "true".
|
|
||||||
*/
|
*/
|
||||||
#define RelationIsMapped(relation) \
|
#define RelationIsMapped(relation) \
|
||||||
((relation)->rd_rel->relfilenode == InvalidOid)
|
(RELKIND_HAS_STORAGE((relation)->rd_rel->relkind) && \
|
||||||
|
((relation)->rd_rel->relfilenode == InvalidOid))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RelationOpenSmgr
|
* RelationOpenSmgr
|
||||||
|
@ -224,3 +224,12 @@ SELECT relname, nspname
|
|||||||
---------+---------
|
---------+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
|
-- check that relations without storage don't have relfilenode
|
||||||
|
SELECT relname, relkind
|
||||||
|
FROM pg_class
|
||||||
|
WHERE relkind IN ('v', 'c', 'f', 'p', 'I')
|
||||||
|
AND relfilenode <> 0;
|
||||||
|
relname | relkind
|
||||||
|
---------+---------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
@ -31,3 +31,9 @@ SELECT relname, nspname
|
|||||||
AND NOT EXISTS (SELECT 1 FROM pg_index i WHERE indrelid = c.oid
|
AND NOT EXISTS (SELECT 1 FROM pg_index i WHERE indrelid = c.oid
|
||||||
AND indkey[0] = a.attnum AND indnatts = 1
|
AND indkey[0] = a.attnum AND indnatts = 1
|
||||||
AND indisunique AND indimmediate);
|
AND indisunique AND indimmediate);
|
||||||
|
|
||||||
|
-- check that relations without storage don't have relfilenode
|
||||||
|
SELECT relname, relkind
|
||||||
|
FROM pg_class
|
||||||
|
WHERE relkind IN ('v', 'c', 'f', 'p', 'I')
|
||||||
|
AND relfilenode <> 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user