OSDN Git Service

Add more dependency insertions --- this completes the basic pg_depend
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 16 Jul 2002 22:12:20 +0000 (22:12 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 16 Jul 2002 22:12:20 +0000 (22:12 +0000)
functionality.  Of note: dropping a table that has a SERIAL column
defined now drops the associated sequence automatically.

19 files changed:
doc/src/sgml/release.sgml
src/backend/catalog/heap.c
src/backend/catalog/pg_aggregate.c
src/backend/catalog/pg_constraint.c
src/backend/catalog/pg_depend.c
src/backend/catalog/pg_operator.c
src/backend/catalog/pg_proc.c
src/backend/commands/proclang.c
src/backend/commands/sequence.c
src/backend/commands/tablecmds.c
src/backend/commands/typecmds.c
src/backend/commands/view.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/parser/analyze.c
src/backend/parser/gram.y
src/include/catalog/dependency.h
src/include/nodes/parsenodes.h

index 7fd8c92..f215c84 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.140 2002/07/12 18:43:12 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.141 2002/07/16 22:12:18 tgl Exp $
 -->
 
 <appendix id="release">
@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
 worries about funny characters.
 -->
 <literallayout><![CDATA[
+Sequences created by SERIAL column definitions now auto-drop with the column
 Most forms of DROP now support RESTRICT and CASCADE options
 Recursive SQL functions can be defined
 User-defined procedural languages can register a validator function to check new functions as they are created
index a8700c5..51933d3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.208 2002/07/16 05:53:33 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.209 2002/07/16 22:12:18 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -97,37 +97,37 @@ static void RemoveStatistics(Relation rel);
 static FormData_pg_attribute a1 = {
        0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
        SelfItemPointerAttributeNumber, 0, -1, -1,
-       false, 'p', false, 'i', false, false
+       false, 'p', false, 'i', true, false
 };
 
 static FormData_pg_attribute a2 = {
        0, {"oid"}, OIDOID, 0, sizeof(Oid),
        ObjectIdAttributeNumber, 0, -1, -1,
-       true, 'p', false, 'i', false, false
+       true, 'p', false, 'i', true, false
 };
 
 static FormData_pg_attribute a3 = {
        0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
        MinTransactionIdAttributeNumber, 0, -1, -1,
-       true, 'p', false, 'i', false, false
+       true, 'p', false, 'i', true, false
 };
 
 static FormData_pg_attribute a4 = {
        0, {"cmin"}, CIDOID, 0, sizeof(CommandId),
        MinCommandIdAttributeNumber, 0, -1, -1,
-       true, 'p', false, 'i', false, false
+       true, 'p', false, 'i', true, false
 };
 
 static FormData_pg_attribute a5 = {
        0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
        MaxTransactionIdAttributeNumber, 0, -1, -1,
-       true, 'p', false, 'i', false, false
+       true, 'p', false, 'i', true, false
 };
 
 static FormData_pg_attribute a6 = {
        0, {"cmax"}, CIDOID, 0, sizeof(CommandId),
        MaxCommandIdAttributeNumber, 0, -1, -1,
-       true, 'p', false, 'i', false, false
+       true, 'p', false, 'i', true, false
 };
 
 /*
@@ -139,7 +139,7 @@ static FormData_pg_attribute a6 = {
 static FormData_pg_attribute a7 = {
        0, {"tableoid"}, OIDOID, 0, sizeof(Oid),
        TableOidAttributeNumber, 0, -1, -1,
-       true, 'p', false, 'i', false, false
+       true, 'p', false, 'i', true, false
 };
 
 static Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
@@ -416,6 +416,8 @@ AddNewAttributeTuples(Oid new_rel_oid,
        bool            hasindex;
        Relation        idescs[Num_pg_attr_indices];
        int                     natts = tupdesc->natts;
+       ObjectAddress   myself,
+                                       referenced;
 
        /*
         * open pg_attribute
@@ -430,7 +432,8 @@ AddNewAttributeTuples(Oid new_rel_oid,
                CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
 
        /*
-        * first we add the user attributes..
+        * First we add the user attributes.  This is also a convenient place
+        * to add dependencies on their datatypes.
         */
        dpp = tupdesc->attrs;
        for (i = 0; i < natts; i++)
@@ -451,11 +454,22 @@ AddNewAttributeTuples(Oid new_rel_oid,
                        CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
 
                heap_freetuple(tup);
+
+               myself.classId = RelOid_pg_class;
+               myself.objectId = new_rel_oid;
+               myself.objectSubId = i+1;
+               referenced.classId = RelOid_pg_type;
+               referenced.objectId = (*dpp)->atttypid;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
                dpp++;
        }
 
        /*
-        * next we add the system attributes.  Skip OID if rel has no OIDs.
+        * Next we add the system attributes.  Skip OID if rel has no OIDs.
+        * Skip all for a view.  We don't bother with making datatype
+        * dependencies here, since presumably all these types are pinned.
         */
        if (relkind != RELKIND_VIEW)
        {
@@ -493,7 +507,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
        }
 
        /*
-        * close pg_attribute indices
+        * clean up
         */
        if (hasindex)
                CatalogCloseIndices(Num_pg_attr_indices, idescs);
index be84bf4..28d7e83 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.49 2002/06/20 20:29:26 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.50 2002/07/16 22:12:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include "access/heapam.h"
 #include "catalog/catname.h"
+#include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_aggregate.h"
@@ -53,6 +54,8 @@ AggregateCreate(const char *aggName,
        Oid                     procOid;
        TupleDesc       tupDesc;
        int                     i;
+       ObjectAddress   myself,
+                                       referenced;
 
        /* sanity checks */
        if (!aggName)
@@ -187,4 +190,29 @@ AggregateCreate(const char *aggName,
        }
 
        heap_close(aggdesc, RowExclusiveLock);
+
+       /*
+        * Create dependencies for the aggregate (above and beyond those
+        * already made by ProcedureCreate).  Note: we don't need an explicit
+        * dependency on aggTransType since we depend on it indirectly through
+        * transfn.
+        */
+       myself.classId = RelOid_pg_proc;
+       myself.objectId = procOid;
+       myself.objectSubId = 0;
+
+       /* Depends on transition function */
+       referenced.classId = RelOid_pg_proc;
+       referenced.objectId = transfn;
+       referenced.objectSubId = 0;
+       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+       /* Depends on final function, if any */
+       if (OidIsValid(finalfn))
+       {
+               referenced.classId = RelOid_pg_proc;
+               referenced.objectId = finalfn;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
 }
index 41580f2..96784e7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.2 2002/07/16 05:53:33 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.3 2002/07/16 22:12:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -198,17 +198,11 @@ CreateConstraintEntry(const char *constraintName,
        if (OidIsValid(foreignRelId))
        {
                /*
-                * Register dependency from constraint to foreign relation,
+                * Register normal dependency from constraint to foreign relation,
                 * or to specific column(s) if any are mentioned.
-                *
-                * In normal case of two separate relations, make this a NORMAL
-                * dependency (so dropping the FK table would require CASCADE).
-                * However, for a self-reference just make it AUTO.
                 */
-               DependencyType  deptype;
                ObjectAddress   relobject;
 
-               deptype = (foreignRelId == relId) ? DEPENDENCY_AUTO : DEPENDENCY_NORMAL;
                relobject.classId = RelOid_pg_class;
                relobject.objectId = foreignRelId;
                if (foreignNKeys > 0)
@@ -217,14 +211,14 @@ CreateConstraintEntry(const char *constraintName,
                        {
                                relobject.objectSubId = foreignKey[i];
 
-                               recordDependencyOn(&conobject, &relobject, deptype);
+                               recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
                        }
                }
                else
                {
                        relobject.objectSubId = 0;
 
-                       recordDependencyOn(&conobject, &relobject, deptype);
+                       recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
                }
        }
 
index 75a1ba0..7319cec 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.2 2002/07/16 05:53:33 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.3 2002/07/16 22:12:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -121,6 +121,43 @@ recordMultipleDependencies(const ObjectAddress *depender,
        heap_close(dependDesc, RowExclusiveLock);
 }
 
+/*
+ * deleteDependencyRecordsFor -- delete all records with given depender
+ * classId/objectId.
+ *
+ * This is used when redefining an existing object.  Links leading to the
+ * object do not change, and links leading from it will be recreated
+ * (possibly with some differences from before).
+ */
+void
+deleteDependencyRecordsFor(Oid classId, Oid objectId)
+{
+       Relation                depRel;
+       ScanKeyData             key[2];
+       SysScanDesc             scan;
+       HeapTuple               tup;
+
+       depRel = heap_openr(DependRelationName, RowExclusiveLock);
+
+       ScanKeyEntryInitialize(&key[0], 0x0,
+                                                  Anum_pg_depend_classid, F_OIDEQ,
+                                                  ObjectIdGetDatum(classId));
+       ScanKeyEntryInitialize(&key[1], 0x0,
+                                                  Anum_pg_depend_objid, F_OIDEQ,
+                                                  ObjectIdGetDatum(objectId));
+
+       scan = systable_beginscan(depRel, DependDependerIndex, true,
+                                                         SnapshotNow, 2, key);
+
+       while (HeapTupleIsValid(tup = systable_getnext(scan)))
+       {
+               simple_heap_delete(depRel, &tup->t_self);
+       }
+
+       systable_endscan(scan);
+
+       heap_close(depRel, RowExclusiveLock);
+}
 
 /*
  * isObjectPinned()
index 95eac6b..09c3f6b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.70 2002/06/20 20:29:26 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.71 2002/07/16 22:12:18 tgl Exp $
  *
  * NOTES
  *       these routines moved here from commands/define.c and somewhat cleaned up.
@@ -19,6 +19,7 @@
 
 #include "access/heapam.h"
 #include "catalog/catname.h"
+#include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_operator.h"
@@ -56,6 +57,8 @@ static Oid get_other_operator(List *otherOp,
                                                          Oid leftTypeId, Oid rightTypeId,
                                                          bool isCommutator);
 
+static void makeOperatorDependencies(HeapTuple tuple, Oid pg_operator_relid);
+
 
 /*
  * Check whether a proposed operator name is legal
@@ -271,6 +274,9 @@ OperatorShellMake(const char *operatorName,
                CatalogCloseIndices(Num_pg_operator_indices, idescs);
        }
 
+       /* Add dependencies for the entry */
+       makeOperatorDependencies(tup, RelationGetRelid(pg_operator_desc));
+
        heap_freetuple(tup);
 
        /*
@@ -659,6 +665,9 @@ OperatorCreate(const char *operatorName,
                CatalogCloseIndices(Num_pg_operator_indices, idescs);
        }
 
+       /* Add dependencies for the entry */
+       makeOperatorDependencies(tup, RelationGetRelid(pg_operator_desc));
+
        heap_close(pg_operator_desc, RowExclusiveLock);
 
        /*
@@ -893,3 +902,89 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
 
        heap_close(pg_operator_desc, RowExclusiveLock);
 }
+
+/*
+ * Create dependencies for a new operator (either a freshly inserted
+ * complete operator, a new shell operator, or a just-updated shell).
+ *
+ * NB: the OidIsValid tests in this routine are *all* necessary, in case
+ * the given operator is a shell.
+ */
+static void
+makeOperatorDependencies(HeapTuple tuple, Oid pg_operator_relid)
+{
+       Form_pg_operator        oper = (Form_pg_operator) GETSTRUCT(tuple);
+       ObjectAddress   myself,
+                                       referenced;
+
+       myself.classId = pg_operator_relid;
+       myself.objectId = tuple->t_data->t_oid;
+       myself.objectSubId = 0;
+
+       /* In case we are updating a shell, delete any existing entries */
+       deleteDependencyRecordsFor(myself.classId, myself.objectId);
+
+       /* Dependency on left type */
+       if (OidIsValid(oper->oprleft))
+       {
+               referenced.classId = RelOid_pg_type;
+               referenced.objectId = oper->oprleft;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
+       /* Dependency on right type */
+       if (OidIsValid(oper->oprright))
+       {
+               referenced.classId = RelOid_pg_type;
+               referenced.objectId = oper->oprright;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
+       /* Dependency on result type */
+       if (OidIsValid(oper->oprresult))
+       {
+               referenced.classId = RelOid_pg_type;
+               referenced.objectId = oper->oprresult;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
+       /*
+        * NOTE: we do not consider the operator to depend on the associated
+        * operators oprcom, oprnegate, oprlsortop, oprrsortop, oprltcmpop,
+        * oprgtcmpop.  We would not want to delete this operator if those
+        * go away, but only reset the link fields; which is not a function
+        * that the dependency code can presently handle.  (Something could
+        * perhaps be done with objectSubId though.)  For now, it's okay to
+        * let those links dangle if a referenced operator is removed.
+        */
+
+       /* Dependency on implementation function */
+       if (OidIsValid(oper->oprcode))
+       {
+               referenced.classId = RelOid_pg_proc;
+               referenced.objectId = oper->oprcode;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
+       /* Dependency on restriction selectivity function */
+       if (OidIsValid(oper->oprrest))
+       {
+               referenced.classId = RelOid_pg_proc;
+               referenced.objectId = oper->oprrest;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
+       /* Dependency on join selectivity function */
+       if (OidIsValid(oper->oprjoin))
+       {
+               referenced.classId = RelOid_pg_proc;
+               referenced.objectId = oper->oprjoin;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+}
index a7e3327..18746d9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.76 2002/06/20 20:29:26 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.77 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include "access/heapam.h"
 #include "catalog/catname.h"
+#include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_proc.h"
@@ -76,6 +77,9 @@ ProcedureCreate(const char *procedureName,
        NameData        procname;
        TupleDesc       tupDesc;
        Oid                     retval;
+       bool            is_update;
+       ObjectAddress   myself,
+                                       referenced;
 
        /*
         * sanity checks
@@ -227,6 +231,7 @@ ProcedureCreate(const char *procedureName,
                simple_heap_update(rel, &tup->t_self, tup);
 
                ReleaseSysCache(oldtup);
+               is_update = true;
        }
        else
        {
@@ -237,6 +242,7 @@ ProcedureCreate(const char *procedureName,
 
                tup = heap_formtuple(tupDesc, values, nulls);
                simple_heap_insert(rel, tup);
+               is_update = false;
        }
 
        /* Need to update indices for either the insert or update case */
@@ -250,6 +256,45 @@ ProcedureCreate(const char *procedureName,
        }
 
        retval = tup->t_data->t_oid;
+
+       /*
+        * Create dependencies for the new function.  If we are updating an
+        * existing function, first delete any existing pg_depend entries.
+        */
+       if (is_update)
+               deleteDependencyRecordsFor(RelOid_pg_proc, retval);
+
+       myself.classId = RelOid_pg_proc;
+       myself.objectId = retval;
+       myself.objectSubId = 0;
+
+       /* dependency on implementation language */
+       referenced.classId = get_system_catalog_relid(LanguageRelationName);
+       referenced.objectId = languageObjectId;
+       referenced.objectSubId = 0;
+       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+       /* dependency on return type */
+       if (OidIsValid(returnType))
+       {
+               referenced.classId = RelOid_pg_type;
+               referenced.objectId = returnType;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
+       /* dependency on input types */
+       for (i = 0; i < parameterCount; i++)
+       {
+               if (OidIsValid(typev[i]))
+               {
+                       referenced.classId = RelOid_pg_type;
+                       referenced.objectId = typev[i];
+                       referenced.objectSubId = 0;
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+               }
+       }
+
        heap_freetuple(tup);
 
        heap_close(rel, RowExclusiveLock);
index 56dc320..98b6132 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.35 2002/07/12 18:43:16 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.36 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -49,6 +49,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
        HeapTuple       tup;
        TupleDesc       tupDesc;
        int                     i;
+       ObjectAddress   myself,
+                                       referenced;
 
        /*
         * Check permission
@@ -91,7 +93,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
                                 NameListToString(stmt->plvalidator));
        }
        else
-               valProcOid = 0;
+               valProcOid = InvalidOid;
 
        /*
         * Insert the new language into pg_language
@@ -128,6 +130,28 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
                CatalogCloseIndices(Num_pg_language_indices, idescs);
        }
 
+       /*
+        * Create dependencies for language
+        */
+       myself.classId = RelationGetRelid(rel);
+       myself.objectId = tup->t_data->t_oid;
+       myself.objectSubId = 0;
+
+       /* dependency on the PL handler function */
+       referenced.classId = RelOid_pg_proc;
+       referenced.objectId = procOid;
+       referenced.objectSubId = 0;
+       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+       /* dependency on the validator function, if any */
+       if (OidIsValid(valProcOid))
+       {
+               referenced.classId = RelOid_pg_proc;
+               referenced.objectId = valProcOid;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
        heap_close(rel, RowExclusiveLock);
 }
 
index 1d01361..f8a05b6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.82 2002/06/20 20:29:27 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.83 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -124,11 +124,15 @@ DefineSequence(CreateSeqStmt *seq)
                typnam->setof = FALSE;
                typnam->arrayBounds = NIL;
                typnam->typmod = -1;
+
                coldef = makeNode(ColumnDef);
                coldef->typename = typnam;
+               coldef->is_not_null = true;
                coldef->raw_default = NULL;
                coldef->cooked_default = NULL;
-               coldef->is_not_null = false;
+               coldef->constraints = NIL;
+               coldef->support = NULL;
+
                null[i - 1] = ' ';
 
                switch (i)
index 099c635..391adb0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.22 2002/07/16 05:53:33 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.23 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -239,6 +239,10 @@ DefineRelation(CreateStmt *stmt, char relkind)
         * So, the transformation has to be postponed to this final step of
         * CREATE TABLE.
         *
+        * Another task that's conveniently done at this step is to add
+        * dependency links between columns and supporting relations (such
+        * as SERIAL sequences).
+        *
         * First, scan schema to find new column defaults.
         */
        rawDefaults = NIL;
@@ -247,18 +251,35 @@ DefineRelation(CreateStmt *stmt, char relkind)
        foreach(listptr, schema)
        {
                ColumnDef  *colDef = lfirst(listptr);
-               RawColumnDefault *rawEnt;
 
                attnum++;
 
-               if (colDef->raw_default == NULL)
-                       continue;
-               Assert(colDef->cooked_default == NULL);
+               if (colDef->raw_default != NULL)
+               {
+                       RawColumnDefault *rawEnt;
 
-               rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
-               rawEnt->attnum = attnum;
-               rawEnt->raw_default = colDef->raw_default;
-               rawDefaults = lappend(rawDefaults, rawEnt);
+                       Assert(colDef->cooked_default == NULL);
+
+                       rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+                       rawEnt->attnum = attnum;
+                       rawEnt->raw_default = colDef->raw_default;
+                       rawDefaults = lappend(rawDefaults, rawEnt);
+               }
+
+               if (colDef->support != NULL)
+               {
+                       /* Create dependency for supporting relation for this column */
+                       ObjectAddress   colobject,
+                                               suppobject;
+
+                       colobject.classId = RelOid_pg_class;
+                       colobject.objectId = relationId;
+                       colobject.objectSubId = attnum;
+                       suppobject.classId = RelOid_pg_class;
+                       suppobject.objectId = RangeVarGetRelid(colDef->support, false);
+                       suppobject.objectSubId = 0;
+                       recordDependencyOn(&suppobject, &colobject, DEPENDENCY_INTERNAL);
+               }
        }
 
        /*
@@ -533,6 +554,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                                def->raw_default = NULL;
                                def->cooked_default = NULL;
                                def->constraints = NIL;
+                               def->support = NULL;
                                inhSchema = lappend(inhSchema, def);
                                newattno[parent_attno - 1] = ++child_attno;
                        }
@@ -1524,6 +1546,8 @@ AlterTableAddColumn(Oid myrelid,
        HeapTuple       typeTuple;
        Form_pg_type tform;
        int                     attndims;
+       ObjectAddress   myself,
+                                       referenced;
 
        /*
         * Grab an exclusive lock on the target table, which we will NOT
@@ -1698,6 +1722,17 @@ AlterTableAddColumn(Oid myrelid,
        heap_close(rel, NoLock);        /* close rel but keep lock! */
 
        /*
+        * Add datatype dependency for the new column.
+        */
+       myself.classId = RelOid_pg_class;
+       myself.objectId = myrelid;
+       myself.objectSubId = i;
+       referenced.classId = RelOid_pg_type;
+       referenced.objectId = attribute->atttypid;
+       referenced.objectSubId = 0;
+       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+       /*
         * Make our catalog updates visible for subsequent steps.
         */
        CommandCounterIncrement();
index f148ff6..c94b678 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.5 2002/07/12 18:43:16 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.6 2002/07/16 22:12:19 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -358,15 +358,18 @@ DefineDomain(CreateDomainStmt *stmt)
        char            typtype;
        Datum           datum;
        bool            isnull;
+       Node       *defaultExpr = NULL;
        char       *defaultValue = NULL;
        char       *defaultValueBin = NULL;
        bool            typNotNull = false;
+       bool            nullDefined = false;
        Oid                     basetypelem;
        int32           typNDims = length(stmt->typename->arrayBounds);
        HeapTuple       typeTup;
        List       *schema = stmt->constraints;
        List       *listptr;
        Oid                     basetypeoid;
+       Oid                     domainoid;
        Form_pg_type    baseType;
 
        /* Convert list of names to a name and namespace */
@@ -459,8 +462,6 @@ DefineDomain(CreateDomainStmt *stmt)
        foreach(listptr, schema)
        {
                Constraint *colDef = lfirst(listptr);
-               bool nullDefined = false;
-               Node       *expr;
                ParseState *pstate;
 
                switch (colDef->contype)
@@ -473,47 +474,45 @@ DefineDomain(CreateDomainStmt *stmt)
                         * don't want to cook or fiddle too much.
                         */
                        case CONSTR_DEFAULT:
+                               if (defaultExpr)
+                                       elog(ERROR, "CREATE DOMAIN has multiple DEFAULT expressions");
                                /* Create a dummy ParseState for transformExpr */
                                pstate = make_parsestate(NULL);
                                /*
                                 * Cook the colDef->raw_expr into an expression.
                                 * Note: Name is strictly for error message
                                 */
-                               expr = cookDefault(pstate, colDef->raw_expr,
-                                                                  basetypeoid,
-                                                                  stmt->typename->typmod,
-                                                                  domainName);
+                               defaultExpr = cookDefault(pstate, colDef->raw_expr,
+                                                                                 basetypeoid,
+                                                                                 stmt->typename->typmod,
+                                                                                 domainName);
                                /*
                                 * Expression must be stored as a nodeToString result,
                                 * but we also require a valid textual representation
                                 * (mainly to make life easier for pg_dump).
                                 */
-                               defaultValue = deparse_expression(expr,
+                               defaultValue = deparse_expression(defaultExpr,
                                                                deparse_context_for(domainName,
                                                                                                        InvalidOid),
                                                                                                   false);
-                               defaultValueBin = nodeToString(expr);
+                               defaultValueBin = nodeToString(defaultExpr);
                                break;
 
                        /*
                         * Find the NULL constraint.
                         */
                        case CONSTR_NOTNULL:
-                               if (nullDefined) {
+                               if (nullDefined)
                                        elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
-                               } else {
-                                       typNotNull = true;
-                                       nullDefined = true;
-                               }
+                               typNotNull = true;
+                               nullDefined = true;
                                break;
 
                        case CONSTR_NULL:
-                               if (nullDefined) {
+                               if (nullDefined)
                                        elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
-                               } else {
-                                       typNotNull = false;
-                                       nullDefined = true;
-                               }
+                               typNotNull = false;
+                               nullDefined = true;
                                break;
 
                        case CONSTR_UNIQUE:
@@ -544,28 +543,44 @@ DefineDomain(CreateDomainStmt *stmt)
        /*
         * Have TypeCreate do all the real work.
         */
-       TypeCreate(domainName,                  /* type name */
-                          domainNamespace,             /* namespace */
-                          InvalidOid,                  /* preassigned type oid (none here) */
-                          InvalidOid,                  /* relation oid (n/a here) */
-                          internalLength,              /* internal size */
-                          externalLength,              /* external size */
-                          'd',                                 /* type-type (domain type) */
-                          delimiter,                   /* array element delimiter */
-                          inputProcedure,              /* input procedure */
-                          outputProcedure,             /* output procedure */
-                          receiveProcedure,    /* receive procedure */
-                          sendProcedure,               /* send procedure */
-                          basetypelem,                 /* element type ID */
-                          basetypeoid,                 /* base type ID */
-                          defaultValue,                /* default type value (text) */
-                          defaultValueBin,             /* default type value (binary) */
-                          byValue,                             /* passed by value */
-                          alignment,                   /* required alignment */
-                          storage,                             /* TOAST strategy */
-                          stmt->typename->typmod, /* typeMod value */
-                          typNDims,                    /* Array dimensions for base type */
-                          typNotNull);                 /* Type NOT NULL */
+       domainoid =
+               TypeCreate(domainName,                  /* type name */
+                                  domainNamespace,             /* namespace */
+                                  InvalidOid,                  /* preassigned type oid (none here) */
+                                  InvalidOid,                  /* relation oid (n/a here) */
+                                  internalLength,              /* internal size */
+                                  externalLength,              /* external size */
+                                  'd',                                 /* type-type (domain type) */
+                                  delimiter,                   /* array element delimiter */
+                                  inputProcedure,              /* input procedure */
+                                  outputProcedure,             /* output procedure */
+                                  receiveProcedure,    /* receive procedure */
+                                  sendProcedure,               /* send procedure */
+                                  basetypelem,                 /* element type ID */
+                                  basetypeoid,                 /* base type ID */
+                                  defaultValue,                /* default type value (text) */
+                                  defaultValueBin,             /* default type value (binary) */
+                                  byValue,                             /* passed by value */
+                                  alignment,                   /* required alignment */
+                                  storage,                             /* TOAST strategy */
+                                  stmt->typename->typmod, /* typeMod value */
+                                  typNDims,                    /* Array dimensions for base type */
+                                  typNotNull);                 /* Type NOT NULL */
+
+       /*
+        * Add any dependencies needed for the default expression.
+        */
+       if (defaultExpr)
+       {
+               ObjectAddress   domobject;
+
+               domobject.classId = RelOid_pg_type;
+               domobject.objectId = domainoid;
+               domobject.objectSubId = 0;
+
+               recordDependencyOnExpr(&domobject, defaultExpr, NIL,
+                                                          DEPENDENCY_NORMAL);
+       }
 
        /*
         * Now we can clean up.
index 519df15..faaff48 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $Id: view.c,v 1.66 2002/07/12 18:43:16 tgl Exp $
+ *     $Id: view.c,v 1.67 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -72,6 +72,7 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist)
                        def->raw_default = NULL;
                        def->cooked_default = NULL;
                        def->constraints = NIL;
+                       def->support = NULL;
 
                        attrList = lappend(attrList, def);
                }
index 4e568a3..426180d 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.193 2002/07/12 18:43:16 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.194 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1749,6 +1749,7 @@ _copyColumnDef(ColumnDef *from)
        if (from->cooked_default)
                newnode->cooked_default = pstrdup(from->cooked_default);
        Node_Copy(from, newnode, constraints);
+       Node_Copy(from, newnode, support);
 
        return newnode;
 }
index e15870b..ed5d638 100644 (file)
@@ -20,7 +20,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.140 2002/07/12 18:43:16 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.141 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1636,6 +1636,8 @@ _equalColumnDef(ColumnDef *a, ColumnDef *b)
                return false;
        if (!equal(a->constraints, b->constraints))
                return false;
+       if (!equal(a->support, b->support))
+               return false;
 
        return true;
 }
index ae3139a..a9e6a83 100644 (file)
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.162 2002/07/12 18:43:16 tgl Exp $
+ *     $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.163 2002/07/16 22:12:19 tgl Exp $
  *
  * NOTES
  *       Every (plan) node in POSTGRES has an associated "out" routine which
@@ -183,6 +183,8 @@ _outColumnDef(StringInfo str, ColumnDef *node)
        _outToken(str, node->cooked_default);
        appendStringInfo(str, " :constraints ");
        _outNode(str, node->constraints);
+       appendStringInfo(str, " :support ");
+       _outNode(str, node->support);
 }
 
 static void
index 2fbca50..6337b61 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.238 2002/07/12 18:43:17 tgl Exp $
+ *     $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.239 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -848,6 +848,12 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
                cxt->blist = lappend(cxt->blist, seqstmt);
 
                /*
+                * Mark the ColumnDef so that during execution, an appropriate
+                * dependency will be added from the sequence to the column.
+                */
+               column->support = makeRangeVar(snamespace, sname);
+
+               /*
                 * Create appropriate constraints for SERIAL.  We do this in full,
                 * rather than shortcutting, so that we will detect any
                 * conflicting constraints the user wrote (like a different
index ef83d92..9b8e526 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.340 2002/07/14 23:38:13 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.341 2002/07/16 22:12:20 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -1852,10 +1852,11 @@ CreateAsElement:
                                        ColumnDef *n = makeNode(ColumnDef);
                                        n->colname = $1;
                                        n->typename = NULL;
+                                       n->is_not_null = false;
                                        n->raw_default = NULL;
                                        n->cooked_default = NULL;
-                                       n->is_not_null = FALSE;
-                                       n->constraints = NULL;
+                                       n->constraints = NIL;
+                                       n->support = NULL;
                                        $$ = (Node *)n;
                                }
                ;
index bcadaee..b278007 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: dependency.h,v 1.2 2002/07/16 05:53:34 tgl Exp $
+ * $Id: dependency.h,v 1.3 2002/07/16 22:12:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -98,4 +98,6 @@ extern void recordMultipleDependencies(const ObjectAddress *depender,
                                                                           int nreferenced,
                                                                           DependencyType behavior);
 
+extern void deleteDependencyRecordsFor(Oid classId, Oid objectId);
+
 #endif   /* DEPENDENCY_H */
index f054299..c0933f8 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.186 2002/07/14 23:38:13 tgl Exp $
+ * $Id: parsenodes.h,v 1.187 2002/07/16 22:12:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -269,6 +269,10 @@ typedef struct BooleanTest
  * parsetree produced by gram.y, but transformCreateStmt will remove
  * the item and set raw_default instead.  CONSTR_DEFAULT items
  * should not appear in any subsequent processing.
+ *
+ * The "support" field, if not null, denotes a supporting relation that
+ * should be linked by an internal dependency to the column.  Currently
+ * this is only used to link a SERIAL column's sequence to the column.
  */
 typedef struct ColumnDef
 {
@@ -280,6 +284,7 @@ typedef struct ColumnDef
                                                                 * tree) */
        char       *cooked_default; /* nodeToString representation */
        List       *constraints;        /* other constraints on column */
+       RangeVar   *support;            /* supporting relation, if any */
 } ColumnDef;
 
 /*