Add more dependency insertions --- this completes the basic pg_depend
authorTom Lane
Tue, 16 Jul 2002 22:12:20 +0000 (22:12 +0000)
committerTom Lane
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 7fd8c92e371b85bd131d6376f7d9993bb5291694..f215c84b93e0c0c73808f36020b071b6302ba95f 100644 (file)
@@ -1,5 +1,5 @@
 
 
 
@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
 worries about funny characters.
 -->
 
+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 a8700c5efd9f8d8dc4701a1bfc674e105436034a..51933d32ede8891df61e5f1be660bb77a4dd3437 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 be84bf4acf281d2251b71026355aad91ab50bc49..28d7e83f575e8026e191ec2304fd3ebf678ffb5c 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 41580f2c53fe518a7bbe687d5227484c6dfdf277..96784e73e36f164415ff8a9a49621c17c4622a42 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 75a1ba01c4e44c1c7eaabe02e6f6c15440cd73c6..7319cec682e24bcb8518a188c0d4d2a6d2b48be1 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 95eac6bd4ef113c2d3f9bdc9e11508ec54ef887d..09c3f6be76fb8b653b0e68d1d2f059e4b01de20b 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 a7e33270063bdf7b9388c66fd476e6a9ef3f586b..18746d9e2196d058b14c3be0990c1f9ecf9e85d2 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 56dc320e2ef4416db7fce6b742ee2365c8b9de38..98b613242625b11126c5d8a4208cd0132651edab 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 1d013612da43a6d6225bddd94c580c68b1ab0e64..f8a05b619de484897ddb9e88cec4e34b8ef0627d 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 099c6351b7f5f4c5e6688aa14d9d1d057f3e2f1e..391adb042254ab7962ead36f1d25ee1f50353fc6 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
@@ -1697,6 +1721,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.
     */
index f148ff658918db7401d530d87d1f4cc65f492d0e..c94b67883be030428ae32e91a543395b43dc5aa2 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 519df157184960b1192f06be935e5db9e0393ae9..faaff48fa053fc7a0fe7ad4d707e04798b90ff98 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 4e568a3c531ba5daa9bbb13a6b55d631dfe51dd4..426180dc1111d04bbb7ece656b9bc9530d70a99d 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 e15870b2c800b4f4fc4534317e51a59136a4e0bb..ed5d638f0cb6b522af8e508b205512eada815ad0 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 ae3139a6ea65e06f396b25ff5958b90a3b25bd5d..a9e6a8382d52807312b9b283be22ceb9254fb7af 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 2fbca505987b7b84e164d526cdb9dd717cb14e0b..6337b61f2acda5ddb1f3e5c54328cc14302e0f8d 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -847,6 +847,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
index ef83d92a6d39b0cdd366e586eeab2bce58a48f77..9b8e52620a6879750b231741b33472eb8d3b6806 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 bcadaee732f2ab125b9bc1b3efbcfc5388a41ef8..b2780071ff30d345642e4c8b810d71114c77553f 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 f0542990f2e5d1f9cc0e2c8777ec96f54dc5d31c..c0933f8ae7ffbbb8c5a7abfcafadf41752586a07 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;
 
 /*