*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
static int checkAttrExists(const char *attributeName,
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
-setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
+static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
/* ----------------------------------------------------------------
int numberOfAttributes;
Oid relationId;
Relation rel;
- List *inheritList;
TupleDesc descriptor;
+ List *inheritOids;
List *old_constraints;
List *rawDefaults;
List *listptr;
StrNCpy(relname, stmt->relname, NAMEDATALEN);
/* ----------------
- * Handle parameters
- * XXX parameter handling missing below.
+ * Look up inheritance ancestors and generate relation schema,
+ * including inherited attributes.
* ----------------
*/
- inheritList = stmt->inhRelnames;
-
- /* ----------------
- * generate relation schema, including inherited attributes.
- * ----------------
- */
- schema = MergeAttributes(schema, inheritList, &old_constraints);
+ schema = MergeAttributes(schema, stmt->inhRelnames,
+ &inheritOids, &old_constraints);
numberOfAttributes = length(schema);
if (numberOfAttributes <= 0)
- {
- elog(ERROR, "DefineRelation: %s",
- "please inherit from a relation or define an attribute");
- }
+ elog(ERROR, "DefineRelation: please inherit from a relation or define an attribute");
/* ----------------
* create a relation descriptor from the relation schema
relkind, stmt->istemp,
allowSystemTableMods);
- StoreCatalogInheritance(relationId, inheritList);
+ StoreCatalogInheritance(relationId, inheritOids);
/*
* We must bump the command counter to make the newly-created relation
* MergeAttributes
* Returns new schema given initial schema and supers.
*
+ * Input arguments:
*
* 'schema' is the column/attribute definition for the table. (It's a list
* 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:
* The order in which the attributes are inherited is very important.
* stud_emp {7:percent}
*/
static List *
-MergeAttributes(List *schema, List *supers, List **supconstr)
+MergeAttributes(List *schema, List *supers,
+ List **supOids, List **supconstr)
{
List *entry;
List *inhSchema = NIL;
+ List *parentOids = NIL;
List *constraints = NIL;
- int attnums;
+ int attnums;
/*
* Validates that there are no duplications. Validity checking of
*/
ColumnDef *restdef = lfirst(rest);
- if (!strcmp(coldef->colname, restdef->colname))
+ if (strcmp(coldef->colname, restdef->colname) == 0)
{
elog(ERROR, "CREATE TABLE: attribute \"%s\" duplicated",
coldef->colname);
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",
strVal(lfirst(entry)));
int i, attidx, attno_exist;
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);
tupleDesc = RelationGetDescr(relation);
/* allocate a new attribute number table and initialize */
partialAttidx [i] = 0;
constr = tupleDesc->constr;
- if (relation->rd_rel->relkind != RELKIND_RELATION)
- elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", name);
-
attidx = 0;
for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--)
{
* put the inherited schema before our the schema for this table
*/
schema = nconc(inhSchema, schema);
+
+ *supOids = parentOids;
*supconstr = constraints;
return schema;
}
/*
* StoreCatalogInheritance
* 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
StoreCatalogInheritance(Oid relationId, List *supers)
TupleDesc desc;
int16 seqNumber;
List *entry;
- List *idList;
HeapTuple tuple;
/* ----------------
return;
/* ----------------
- * Catalog INHERITS information.
+ * Catalog INHERITS information using direct ancestors only.
* ----------------
*/
relation = heap_openr(InheritsRelationName, RowExclusiveLock);
desc = RelationGetDescr(relation);
seqNumber = 1;
- idList = NIL;
foreach(entry, supers)
{
- Oid entryOid;
+ Oid entryOid = lfirsti(entry);
Datum datum[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[1] = ObjectIdGetDatum(entryOid); /* inhparent */
datum[2] = Int16GetDatum(seqNumber); /* inhseqno */
heap_close(relation, RowExclusiveLock);
/* ----------------
- * Catalog IPL information.
+ * Expand supers list to include indirect ancestors as well.
*
* 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.
- * 3. remove all but last of duplicates.
- * 4. store result.
+ * 2. remove all but last of duplicates.
* ----------------
*/
/* ----------------
- * 1.
+ * 1. append after each relationId, its superclasses, recursively.
* ----------------
*/
- foreach(entry, idList)
+ foreach(entry, supers)
{
HeapTuple tuple;
Oid id;
}
/* ----------------
- * 2.
+ * 2. remove all but last of duplicates.
* ----------------
*/
- foreach(entry, idList)
+ foreach(entry, supers)
{
- Oid name;
+ Oid thisone;
+ bool found;
List *rest;
- bool found = false;
again:
- name = lfirsti(entry);
+ thisone = lfirsti(entry);
+ found = false;
foreach(rest, lnext(entry))
{
- if (name == lfirsti(rest))
+ if (thisone == lfirsti(rest))
{
found = true;
break;
{
/*
- * entry list must be of length >= 2 or else no match
- *
- * so, remove this entry.
+ * found a later duplicate, so remove this entry.
*/
- lfirst(entry) = lfirst(lnext(entry));
+ lfirsti(entry) = lfirsti(lnext(entry));
lnext(entry) = lnext(lnext(entry));
- found = false;
goto again;
}
}
/* ----------------
- * 3.
+ * Catalog IPL information using expanded list.
* ----------------
*/
relation = heap_openr(InheritancePrecidenceListRelationName, RowExclusiveLock);
seqNumber = 1;
- foreach(entry, idList)
+ foreach(entry, supers)
{
Datum datum[Natts_pg_ipl];
char nullarr[Natts_pg_ipl];
/*
- * 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
-checkAttrExists(const char *attributeName, const char *attributeType, List *schema)
+checkAttrExists(const char *attributeName, const char *attributeType,
+ List *schema)
{
List *s;
int i = 0;