mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
Adjust setRelhassubclassInRelation() to not perform actual heap_update
when the pg_class.relhassubclass value is already correct. This should avoid most cases of the 'tuple concurrently updated' problem that Robert Creager recently complained about. Also remove a bunch of dead code in StoreCatalogInheritance() --- it was still computing the complete list of direct and indirect inheritance ancestors, though that list has not been needed since we got rid of the pg_ipl catalog.
This commit is contained in:
parent
4a2c34d4a0
commit
e7261c46aa
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.89 2003/10/12 23:19:21 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.90 2003/10/13 20:02:52 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -47,6 +47,7 @@
|
|||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
|
#include "utils/inval.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/relcache.h"
|
#include "utils/relcache.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
@ -558,7 +559,6 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
|||||||
parent->relname)));
|
parent->relname)));
|
||||||
|
|
||||||
parentOids = lappendo(parentOids, RelationGetRelid(relation));
|
parentOids = lappendo(parentOids, RelationGetRelid(relation));
|
||||||
setRelhassubclassInRelation(RelationGetRelid(relation), true);
|
|
||||||
|
|
||||||
parentHasOids |= relation->rd_rel->relhasoids;
|
parentHasOids |= relation->rd_rel->relhasoids;
|
||||||
|
|
||||||
@ -869,7 +869,6 @@ change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
|
|||||||
* Updates the system catalogs with proper inheritance information.
|
* Updates the system catalogs with proper inheritance information.
|
||||||
*
|
*
|
||||||
* supers is a list of the OIDs of the new relation's direct ancestors.
|
* supers is a list of the OIDs of the new relation's direct ancestors.
|
||||||
* NB: it is destructively changed to include indirect ancestors.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
StoreCatalogInheritance(Oid relationId, List *supers)
|
StoreCatalogInheritance(Oid relationId, List *supers)
|
||||||
@ -890,7 +889,12 @@ StoreCatalogInheritance(Oid relationId, List *supers)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Store INHERITS information in pg_inherits using direct ancestors
|
* Store INHERITS information in pg_inherits using direct ancestors
|
||||||
* only. Also enter dependencies on the direct ancestors.
|
* only. Also enter dependencies on the direct ancestors, and make sure
|
||||||
|
* they are marked with relhassubclass = true.
|
||||||
|
*
|
||||||
|
* (Once upon a time, both direct and indirect ancestors were found here
|
||||||
|
* and then entered into pg_ipl. Since that catalog doesn't exist anymore,
|
||||||
|
* there's no need to look for indirect ancestors.)
|
||||||
*/
|
*/
|
||||||
relation = heap_openr(InheritsRelationName, RowExclusiveLock);
|
relation = heap_openr(InheritsRelationName, RowExclusiveLock);
|
||||||
desc = RelationGetDescr(relation);
|
desc = RelationGetDescr(relation);
|
||||||
@ -898,14 +902,14 @@ StoreCatalogInheritance(Oid relationId, List *supers)
|
|||||||
seqNumber = 1;
|
seqNumber = 1;
|
||||||
foreach(entry, supers)
|
foreach(entry, supers)
|
||||||
{
|
{
|
||||||
Oid entryOid = lfirsto(entry);
|
Oid parentOid = lfirsto(entry);
|
||||||
Datum datum[Natts_pg_inherits];
|
Datum datum[Natts_pg_inherits];
|
||||||
char nullarr[Natts_pg_inherits];
|
char nullarr[Natts_pg_inherits];
|
||||||
ObjectAddress childobject,
|
ObjectAddress childobject,
|
||||||
parentobject;
|
parentobject;
|
||||||
|
|
||||||
datum[0] = ObjectIdGetDatum(relationId); /* inhrel */
|
datum[0] = ObjectIdGetDatum(relationId); /* inhrel */
|
||||||
datum[1] = ObjectIdGetDatum(entryOid); /* inhparent */
|
datum[1] = ObjectIdGetDatum(parentOid); /* inhparent */
|
||||||
datum[2] = Int16GetDatum(seqNumber); /* inhseqno */
|
datum[2] = Int16GetDatum(seqNumber); /* inhseqno */
|
||||||
|
|
||||||
nullarr[0] = ' ';
|
nullarr[0] = ' ';
|
||||||
@ -924,7 +928,7 @@ StoreCatalogInheritance(Oid relationId, List *supers)
|
|||||||
* Store a dependency too
|
* Store a dependency too
|
||||||
*/
|
*/
|
||||||
parentobject.classId = RelOid_pg_class;
|
parentobject.classId = RelOid_pg_class;
|
||||||
parentobject.objectId = entryOid;
|
parentobject.objectId = parentOid;
|
||||||
parentobject.objectSubId = 0;
|
parentobject.objectSubId = 0;
|
||||||
childobject.classId = RelOid_pg_class;
|
childobject.classId = RelOid_pg_class;
|
||||||
childobject.objectId = relationId;
|
childobject.objectId = relationId;
|
||||||
@ -932,85 +936,15 @@ StoreCatalogInheritance(Oid relationId, List *supers)
|
|||||||
|
|
||||||
recordDependencyOn(&childobject, &parentobject, DEPENDENCY_NORMAL);
|
recordDependencyOn(&childobject, &parentobject, DEPENDENCY_NORMAL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark the parent as having subclasses.
|
||||||
|
*/
|
||||||
|
setRelhassubclassInRelation(parentOid, true);
|
||||||
|
|
||||||
seqNumber += 1;
|
seqNumber += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_close(relation, RowExclusiveLock);
|
heap_close(relation, RowExclusiveLock);
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* Expand supers list to include indirect ancestors as well.
|
|
||||||
*
|
|
||||||
* Algorithm:
|
|
||||||
* 0. begin with list of direct superclasses.
|
|
||||||
* 1. append after each relationId, its superclasses, recursively.
|
|
||||||
* 2. remove all but last of duplicates.
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 1. append after each relationId, its superclasses, recursively.
|
|
||||||
*/
|
|
||||||
foreach(entry, supers)
|
|
||||||
{
|
|
||||||
Oid id = lfirsto(entry);
|
|
||||||
HeapTuple tuple;
|
|
||||||
int16 number;
|
|
||||||
List *current;
|
|
||||||
List *next;
|
|
||||||
|
|
||||||
current = entry;
|
|
||||||
next = lnext(entry);
|
|
||||||
|
|
||||||
for (number = 1;; number += 1)
|
|
||||||
{
|
|
||||||
tuple = SearchSysCache(INHRELID,
|
|
||||||
ObjectIdGetDatum(id),
|
|
||||||
Int16GetDatum(number),
|
|
||||||
0, 0);
|
|
||||||
if (!HeapTupleIsValid(tuple))
|
|
||||||
break;
|
|
||||||
|
|
||||||
lnext(current) = lconso(((Form_pg_inherits)
|
|
||||||
GETSTRUCT(tuple))->inhparent,
|
|
||||||
NIL);
|
|
||||||
current = lnext(current);
|
|
||||||
|
|
||||||
ReleaseSysCache(tuple);
|
|
||||||
}
|
|
||||||
lnext(current) = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 2. remove all but last of duplicates.
|
|
||||||
*/
|
|
||||||
foreach(entry, supers)
|
|
||||||
{
|
|
||||||
Oid thisone;
|
|
||||||
bool found;
|
|
||||||
List *rest;
|
|
||||||
|
|
||||||
again:
|
|
||||||
found = false;
|
|
||||||
thisone = lfirsto(entry);
|
|
||||||
foreach(rest, lnext(entry))
|
|
||||||
{
|
|
||||||
if (thisone == lfirsto(rest))
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* found a later duplicate, so remove this entry.
|
|
||||||
*/
|
|
||||||
lfirsto(entry) = lfirsto(lnext(entry));
|
|
||||||
lnext(entry) = lnext(lnext(entry));
|
|
||||||
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1044,9 +978,14 @@ setRelhassubclassInRelation(Oid relationId, bool relhassubclass)
|
|||||||
{
|
{
|
||||||
Relation relationRelation;
|
Relation relationRelation;
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
|
Form_pg_class classtuple;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch a modifiable copy of the tuple, modify it, update pg_class.
|
* Fetch a modifiable copy of the tuple, modify it, update pg_class.
|
||||||
|
*
|
||||||
|
* If the tuple already has the right relhassubclass setting, we
|
||||||
|
* don't need to update it, but we still need to issue an SI inval
|
||||||
|
* message.
|
||||||
*/
|
*/
|
||||||
relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
|
relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
|
||||||
tuple = SearchSysCacheCopy(RELOID,
|
tuple = SearchSysCacheCopy(RELOID,
|
||||||
@ -1054,12 +993,21 @@ setRelhassubclassInRelation(Oid relationId, bool relhassubclass)
|
|||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
elog(ERROR, "cache lookup failed for relation %u", relationId);
|
elog(ERROR, "cache lookup failed for relation %u", relationId);
|
||||||
|
classtuple = (Form_pg_class) GETSTRUCT(tuple);
|
||||||
|
|
||||||
((Form_pg_class) GETSTRUCT(tuple))->relhassubclass = relhassubclass;
|
if (classtuple->relhassubclass != relhassubclass)
|
||||||
simple_heap_update(relationRelation, &tuple->t_self, tuple);
|
{
|
||||||
|
classtuple->relhassubclass = relhassubclass;
|
||||||
|
simple_heap_update(relationRelation, &tuple->t_self, tuple);
|
||||||
|
|
||||||
/* keep the catalog indexes up to date */
|
/* keep the catalog indexes up to date */
|
||||||
CatalogUpdateIndexes(relationRelation, tuple);
|
CatalogUpdateIndexes(relationRelation, tuple);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* no need to change tuple, but force relcache rebuild anyway */
|
||||||
|
CacheInvalidateRelcache(relationId);
|
||||||
|
}
|
||||||
|
|
||||||
heap_freetuple(tuple);
|
heap_freetuple(tuple);
|
||||||
heap_close(relationRelation, RowExclusiveLock);
|
heap_close(relationRelation, RowExclusiveLock);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user