mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
tableam: relation creation, VACUUM FULL/CLUSTER, SET TABLESPACE.
This moves the responsibility for: - creating the storage necessary for a relation, including creating a new relfilenode for a relation with existing storage - non-transactional truncation of a relation - VACUUM FULL / CLUSTER's rewrite of a table below tableam. This is fairly straight forward, with a bit of complexity smattered in to move the computation of xid / multixid horizons below the AM, as they don't make sense for every table AM. Author: Andres Freund Discussion: https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
This commit is contained in:
77
src/backend/utils/cache/relcache.c
vendored
77
src/backend/utils/cache/relcache.c
vendored
@ -3422,31 +3422,16 @@ RelationBuildLocalRelation(const char *relname,
|
||||
* such as TRUNCATE or rebuilding an index from scratch.
|
||||
*
|
||||
* Caller must already hold exclusive lock on the relation.
|
||||
*
|
||||
* The relation is marked with relfrozenxid = freezeXid (InvalidTransactionId
|
||||
* must be passed for indexes and sequences). This should be a lower bound on
|
||||
* the XIDs that will be put into the new relation contents.
|
||||
*
|
||||
* The new filenode's persistence is set to the given value. This is useful
|
||||
* for the cases that are changing the relation's persistence; other callers
|
||||
* need to pass the original relpersistence value.
|
||||
*/
|
||||
void
|
||||
RelationSetNewRelfilenode(Relation relation, char persistence,
|
||||
TransactionId freezeXid, MultiXactId minmulti)
|
||||
RelationSetNewRelfilenode(Relation relation, char persistence)
|
||||
{
|
||||
Oid newrelfilenode;
|
||||
RelFileNodeBackend newrnode;
|
||||
Relation pg_class;
|
||||
HeapTuple tuple;
|
||||
Form_pg_class classform;
|
||||
|
||||
/* Indexes, sequences must have Invalid frozenxid; other rels must not */
|
||||
Assert((relation->rd_rel->relkind == RELKIND_INDEX ||
|
||||
relation->rd_rel->relkind == RELKIND_SEQUENCE) ?
|
||||
freezeXid == InvalidTransactionId :
|
||||
TransactionIdIsNormal(freezeXid));
|
||||
Assert(TransactionIdIsNormal(freezeXid) == MultiXactIdIsValid(minmulti));
|
||||
MultiXactId minmulti = InvalidMultiXactId;
|
||||
TransactionId freezeXid = InvalidTransactionId;
|
||||
|
||||
/* Allocate a new relfilenode */
|
||||
newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
|
||||
@ -3464,18 +3449,6 @@ RelationSetNewRelfilenode(Relation relation, char persistence,
|
||||
RelationGetRelid(relation));
|
||||
classform = (Form_pg_class) GETSTRUCT(tuple);
|
||||
|
||||
/*
|
||||
* Create storage for the main fork of the new relfilenode.
|
||||
*
|
||||
* NOTE: any conflict in relfilenode value will be caught here, if
|
||||
* GetNewRelFileNode messes up for any reason.
|
||||
*/
|
||||
newrnode.node = relation->rd_node;
|
||||
newrnode.node.relNode = newrelfilenode;
|
||||
newrnode.backend = relation->rd_backend;
|
||||
RelationCreateStorage(newrnode.node, persistence);
|
||||
smgrclosenode(newrnode);
|
||||
|
||||
/*
|
||||
* Schedule unlinking of the old storage at transaction commit.
|
||||
*/
|
||||
@ -3490,9 +3463,51 @@ RelationSetNewRelfilenode(Relation relation, char persistence,
|
||||
RelationMapUpdateMap(RelationGetRelid(relation),
|
||||
newrelfilenode,
|
||||
relation->rd_rel->relisshared,
|
||||
false);
|
||||
true);
|
||||
else
|
||||
{
|
||||
relation->rd_rel->relfilenode = newrelfilenode;
|
||||
classform->relfilenode = newrelfilenode;
|
||||
}
|
||||
|
||||
RelationInitPhysicalAddr(relation);
|
||||
|
||||
/*
|
||||
* Create storage for the main fork of the new relfilenode. If it's
|
||||
* table-like object, call into table AM to do so, which'll also create
|
||||
* the table's init fork.
|
||||
*
|
||||
* NOTE: any conflict in relfilenode value will be caught here, if
|
||||
* GetNewRelFileNode messes up for any reason.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create storage for relation.
|
||||
*/
|
||||
switch (relation->rd_rel->relkind)
|
||||
{
|
||||
/* shouldn't be called for these */
|
||||
case RELKIND_VIEW:
|
||||
case RELKIND_COMPOSITE_TYPE:
|
||||
case RELKIND_FOREIGN_TABLE:
|
||||
case RELKIND_PARTITIONED_TABLE:
|
||||
case RELKIND_PARTITIONED_INDEX:
|
||||
elog(ERROR, "should not have storage");
|
||||
break;
|
||||
|
||||
case RELKIND_INDEX:
|
||||
case RELKIND_SEQUENCE:
|
||||
RelationCreateStorage(relation->rd_node, persistence);
|
||||
RelationOpenSmgr(relation);
|
||||
break;
|
||||
|
||||
case RELKIND_RELATION:
|
||||
case RELKIND_TOASTVALUE:
|
||||
case RELKIND_MATVIEW:
|
||||
table_relation_set_new_filenode(relation, persistence,
|
||||
&freezeXid, &minmulti);
|
||||
break;
|
||||
}
|
||||
|
||||
/* These changes are safe even for a mapped relation */
|
||||
if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
|
||||
|
Reference in New Issue
Block a user