Commit 468a9704 authored by Tom Lane's avatar Tom Lane

Change StoreCatalogInheritance() to work from a list of parent relation

OIDs rather than names.  Aside from being simpler and faster, this way
doesn't blow up in the face of 'create temp table foo () inherits (foo)'.
Which is a rather odd thing to do, but it seems some people want to.
parent 78099231
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.67 2000/11/16 22:30:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.68 2000/12/14 00:41:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -34,10 +34,10 @@ ...@@ -34,10 +34,10 @@
static int checkAttrExists(const char *attributeName, static int checkAttrExists(const char *attributeName,
const char *attributeType, List *schema); const char *attributeType, List *schema);
static List *MergeAttributes(List *schema, List *supers, List **supconstr); static List *MergeAttributes(List *schema, List *supers,
List **supOids, List **supconstr);
static void StoreCatalogInheritance(Oid relationId, List *supers); static void StoreCatalogInheritance(Oid relationId, List *supers);
static void static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -53,8 +53,8 @@ DefineRelation(CreateStmt *stmt, char relkind) ...@@ -53,8 +53,8 @@ DefineRelation(CreateStmt *stmt, char relkind)
int numberOfAttributes; int numberOfAttributes;
Oid relationId; Oid relationId;
Relation rel; Relation rel;
List *inheritList;
TupleDesc descriptor; TupleDesc descriptor;
List *inheritOids;
List *old_constraints; List *old_constraints;
List *rawDefaults; List *rawDefaults;
List *listptr; List *listptr;
...@@ -67,24 +67,16 @@ DefineRelation(CreateStmt *stmt, char relkind) ...@@ -67,24 +67,16 @@ DefineRelation(CreateStmt *stmt, char relkind)
StrNCpy(relname, stmt->relname, NAMEDATALEN); StrNCpy(relname, stmt->relname, NAMEDATALEN);
/* ---------------- /* ----------------
* Handle parameters * Look up inheritance ancestors and generate relation schema,
* XXX parameter handling missing below. * including inherited attributes.
* ---------------- * ----------------
*/ */
inheritList = stmt->inhRelnames; schema = MergeAttributes(schema, stmt->inhRelnames,
&inheritOids, &old_constraints);
/* ----------------
* generate relation schema, including inherited attributes.
* ----------------
*/
schema = MergeAttributes(schema, inheritList, &old_constraints);
numberOfAttributes = length(schema); numberOfAttributes = length(schema);
if (numberOfAttributes <= 0) if (numberOfAttributes <= 0)
{ elog(ERROR, "DefineRelation: please inherit from a relation or define an attribute");
elog(ERROR, "DefineRelation: %s",
"please inherit from a relation or define an attribute");
}
/* ---------------- /* ----------------
* create a relation descriptor from the relation schema * create a relation descriptor from the relation schema
...@@ -147,7 +139,7 @@ DefineRelation(CreateStmt *stmt, char relkind) ...@@ -147,7 +139,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
relkind, stmt->istemp, relkind, stmt->istemp,
allowSystemTableMods); allowSystemTableMods);
StoreCatalogInheritance(relationId, inheritList); StoreCatalogInheritance(relationId, inheritOids);
/* /*
* We must bump the command counter to make the newly-created relation * We must bump the command counter to make the newly-created relation
...@@ -286,10 +278,15 @@ change_varattnos_of_a_node(Node *node, const AttrNumber *newattno) ...@@ -286,10 +278,15 @@ change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
* MergeAttributes * MergeAttributes
* Returns new schema given initial schema and supers. * Returns new schema given initial schema and supers.
* *
* Input arguments:
* *
* 'schema' is the column/attribute definition for the table. (It's a list * 'schema' is the column/attribute definition for the table. (It's a list
* of ColumnDef's.) It is destructively changed. * of ColumnDef's.) It is destructively changed.
* 'inheritList' is the list of inherited relations (a list of Value(str)'s). * 'supers' is a list of names (as Value objects) of parent relations.
*
* Output arguments:
* 'supOids' receives an integer list of the OIDs of the parent relations.
* 'supconstr' receives a list of constraints belonging to the parents.
* *
* Notes: * Notes:
* The order in which the attributes are inherited is very important. * The order in which the attributes are inherited is very important.
...@@ -314,12 +311,14 @@ change_varattnos_of_a_node(Node *node, const AttrNumber *newattno) ...@@ -314,12 +311,14 @@ change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
* stud_emp {7:percent} * stud_emp {7:percent}
*/ */
static List * static List *
MergeAttributes(List *schema, List *supers, List **supconstr) MergeAttributes(List *schema, List *supers,
List **supOids, List **supconstr)
{ {
List *entry; List *entry;
List *inhSchema = NIL; List *inhSchema = NIL;
List *parentOids = NIL;
List *constraints = NIL; List *constraints = NIL;
int attnums; int attnums;
/* /*
* Validates that there are no duplications. Validity checking of * Validates that there are no duplications. Validity checking of
...@@ -338,7 +337,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr) ...@@ -338,7 +337,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
*/ */
ColumnDef *restdef = lfirst(rest); ColumnDef *restdef = lfirst(rest);
if (!strcmp(coldef->colname, restdef->colname)) if (strcmp(coldef->colname, restdef->colname) == 0)
{ {
elog(ERROR, "CREATE TABLE: attribute \"%s\" duplicated", elog(ERROR, "CREATE TABLE: attribute \"%s\" duplicated",
coldef->colname); coldef->colname);
...@@ -351,7 +350,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr) ...@@ -351,7 +350,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
foreach(rest, lnext(entry)) foreach(rest, lnext(entry))
{ {
if (!strcmp(strVal(lfirst(entry)), strVal(lfirst(rest)))) if (strcmp(strVal(lfirst(entry)), strVal(lfirst(rest))) == 0)
{ {
elog(ERROR, "CREATE TABLE: inherited relation \"%s\" duplicated", elog(ERROR, "CREATE TABLE: inherited relation \"%s\" duplicated",
strVal(lfirst(entry))); strVal(lfirst(entry)));
...@@ -376,6 +375,11 @@ MergeAttributes(List *schema, List *supers, List **supconstr) ...@@ -376,6 +375,11 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
int i, attidx, attno_exist; int i, attidx, attno_exist;
relation = heap_openr(name, AccessShareLock); relation = heap_openr(name, AccessShareLock);
if (relation->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", name);
parentOids = lappendi(parentOids, relation->rd_id);
setRelhassubclassInRelation(relation->rd_id, true); setRelhassubclassInRelation(relation->rd_id, true);
tupleDesc = RelationGetDescr(relation); tupleDesc = RelationGetDescr(relation);
/* allocate a new attribute number table and initialize */ /* allocate a new attribute number table and initialize */
...@@ -391,9 +395,6 @@ MergeAttributes(List *schema, List *supers, List **supconstr) ...@@ -391,9 +395,6 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
partialAttidx [i] = 0; partialAttidx [i] = 0;
constr = tupleDesc->constr; constr = tupleDesc->constr;
if (relation->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", name);
attidx = 0; attidx = 0;
for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--) for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--)
{ {
...@@ -519,6 +520,8 @@ MergeAttributes(List *schema, List *supers, List **supconstr) ...@@ -519,6 +520,8 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
* put the inherited schema before our the schema for this table * put the inherited schema before our the schema for this table
*/ */
schema = nconc(inhSchema, schema); schema = nconc(inhSchema, schema);
*supOids = parentOids;
*supconstr = constraints; *supconstr = constraints;
return schema; return schema;
} }
...@@ -526,6 +529,9 @@ MergeAttributes(List *schema, List *supers, List **supconstr) ...@@ -526,6 +529,9 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
/* /*
* StoreCatalogInheritance * StoreCatalogInheritance
* Updates the system catalogs with proper inheritance information. * Updates the system catalogs with proper inheritance information.
*
* supers is an integer 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)
...@@ -534,7 +540,6 @@ StoreCatalogInheritance(Oid relationId, List *supers) ...@@ -534,7 +540,6 @@ StoreCatalogInheritance(Oid relationId, List *supers)
TupleDesc desc; TupleDesc desc;
int16 seqNumber; int16 seqNumber;
List *entry; List *entry;
List *idList;
HeapTuple tuple; HeapTuple tuple;
/* ---------------- /* ----------------
...@@ -547,32 +552,19 @@ StoreCatalogInheritance(Oid relationId, List *supers) ...@@ -547,32 +552,19 @@ StoreCatalogInheritance(Oid relationId, List *supers)
return; return;
/* ---------------- /* ----------------
* Catalog INHERITS information. * Catalog INHERITS information using direct ancestors only.
* ---------------- * ----------------
*/ */
relation = heap_openr(InheritsRelationName, RowExclusiveLock); relation = heap_openr(InheritsRelationName, RowExclusiveLock);
desc = RelationGetDescr(relation); desc = RelationGetDescr(relation);
seqNumber = 1; seqNumber = 1;
idList = NIL;
foreach(entry, supers) foreach(entry, supers)
{ {
Oid entryOid; Oid entryOid = lfirsti(entry);
Datum datum[Natts_pg_inherits]; Datum datum[Natts_pg_inherits];
char nullarr[Natts_pg_inherits]; char nullarr[Natts_pg_inherits];
entryOid = GetSysCacheOid(RELNAME,
PointerGetDatum(strVal(lfirst(entry))),
0, 0, 0);
if (!OidIsValid(entryOid))
elog(ERROR, "StoreCatalogInheritance: cache lookup failed for relation \"%s\"",
strVal(lfirst(entry)));
/*
* build idList for use below
*/
idList = lappendi(idList, entryOid);
datum[0] = ObjectIdGetDatum(relationId); /* inhrel */ datum[0] = ObjectIdGetDatum(relationId); /* inhrel */
datum[1] = ObjectIdGetDatum(entryOid); /* inhparent */ datum[1] = ObjectIdGetDatum(entryOid); /* inhparent */
datum[2] = Int16GetDatum(seqNumber); /* inhseqno */ datum[2] = Int16GetDatum(seqNumber); /* inhseqno */
...@@ -602,21 +594,20 @@ StoreCatalogInheritance(Oid relationId, List *supers) ...@@ -602,21 +594,20 @@ StoreCatalogInheritance(Oid relationId, List *supers)
heap_close(relation, RowExclusiveLock); heap_close(relation, RowExclusiveLock);
/* ---------------- /* ----------------
* Catalog IPL information. * Expand supers list to include indirect ancestors as well.
* *
* Algorithm: * Algorithm:
* 0. list superclasses (by Oid) in order given (see idList). * 0. begin with list of direct superclasses.
* 1. append after each relationId, its superclasses, recursively. * 1. append after each relationId, its superclasses, recursively.
* 3. remove all but last of duplicates. * 2. remove all but last of duplicates.
* 4. store result.
* ---------------- * ----------------
*/ */
/* ---------------- /* ----------------
* 1. * 1. append after each relationId, its superclasses, recursively.
* ---------------- * ----------------
*/ */
foreach(entry, idList) foreach(entry, supers)
{ {
HeapTuple tuple; HeapTuple tuple;
Oid id; Oid id;
...@@ -649,20 +640,21 @@ StoreCatalogInheritance(Oid relationId, List *supers) ...@@ -649,20 +640,21 @@ StoreCatalogInheritance(Oid relationId, List *supers)
} }
/* ---------------- /* ----------------
* 2. * 2. remove all but last of duplicates.
* ---------------- * ----------------
*/ */
foreach(entry, idList) foreach(entry, supers)
{ {
Oid name; Oid thisone;
bool found;
List *rest; List *rest;
bool found = false;
again: again:
name = lfirsti(entry); thisone = lfirsti(entry);
found = false;
foreach(rest, lnext(entry)) foreach(rest, lnext(entry))
{ {
if (name == lfirsti(rest)) if (thisone == lfirsti(rest))
{ {
found = true; found = true;
break; break;
...@@ -672,20 +664,17 @@ again: ...@@ -672,20 +664,17 @@ again:
{ {
/* /*
* entry list must be of length >= 2 or else no match * found a later duplicate, so remove this entry.
*
* so, remove this entry.
*/ */
lfirst(entry) = lfirst(lnext(entry)); lfirsti(entry) = lfirsti(lnext(entry));
lnext(entry) = lnext(lnext(entry)); lnext(entry) = lnext(lnext(entry));
found = false;
goto again; goto again;
} }
} }
/* ---------------- /* ----------------
* 3. * Catalog IPL information using expanded list.
* ---------------- * ----------------
*/ */
relation = heap_openr(InheritancePrecidenceListRelationName, RowExclusiveLock); relation = heap_openr(InheritancePrecidenceListRelationName, RowExclusiveLock);
...@@ -693,7 +682,7 @@ again: ...@@ -693,7 +682,7 @@ again:
seqNumber = 1; seqNumber = 1;
foreach(entry, idList) foreach(entry, supers)
{ {
Datum datum[Natts_pg_ipl]; Datum datum[Natts_pg_ipl];
char nullarr[Natts_pg_ipl]; char nullarr[Natts_pg_ipl];
...@@ -721,10 +710,12 @@ again: ...@@ -721,10 +710,12 @@ again:
/* /*
* returns the index(star with 1) if attribute already exists in schema, 0 otherwise. * returns the index (starting with 1) if attribute already exists in schema,
* 0 if it doesn't.
*/ */
static int static int
checkAttrExists(const char *attributeName, const char *attributeType, List *schema) checkAttrExists(const char *attributeName, const char *attributeType,
List *schema)
{ {
List *s; List *s;
int i = 0; int i = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment