Re: Bug with Temp table with serial column - Mailing list pgsql-bugs

From Tom Lane
Subject Re: Bug with Temp table with serial column
Date
Msg-id 21881.1044581060@sss.pgh.pa.us
Whole thread Raw
In response to Bug with Temp table with serial column  ("David Heggie" <davidh@intrapower.com.au>)
List pgsql-bugs
"David Heggie" <davidh@intrapower.com.au> writes:
> When creating a temp table with a column which has a type of serial, the error below appears in the postgres log file
afterdisconnection. 

Good catch.  Here's the patch if you need it before 7.3.3 ...

            regards, tom lane


*** src/backend/catalog/dependency.c~    Wed Dec  4 15:00:19 2002
--- src/backend/catalog/dependency.c    Thu Feb  6 20:14:25 2003
***************
*** 99,104 ****
--- 99,109 ----
                    const ObjectAddress *callingObject,
                    ObjectAddresses *oktodelete,
                    Relation depRel);
+ static bool deleteDependentObjects(const ObjectAddress *object,
+                                    const char *objDescription,
+                                    DropBehavior behavior,
+                                    ObjectAddresses *oktodelete,
+                                    Relation depRel);
  static void doDeletion(const ObjectAddress *object);
  static bool find_expr_references_walker(Node *node,
                              find_expr_references_context *context);
***************
*** 172,177 ****
--- 177,240 ----


  /*
+  * deleteWhatDependsOn: attempt to drop everything that depends on the
+  * specified object, though not the object itself.  Behavior is always
+  * CASCADE.
+  *
+  * This is currently used only to clean out the contents of a schema
+  * (namespace): the passed object is a namespace.
+  */
+ void
+ deleteWhatDependsOn(const ObjectAddress *object)
+ {
+     char       *objDescription;
+     Relation    depRel;
+     ObjectAddresses oktodelete;
+
+     /*
+      * Get object description for possible use in failure messages
+      */
+     objDescription = getObjectDescription(object);
+
+     /*
+      * We save some cycles by opening pg_depend just once and passing the
+      * Relation pointer down to all the recursive deletion steps.
+      */
+     depRel = heap_openr(DependRelationName, RowExclusiveLock);
+
+     /*
+      * Construct a list of objects that are reachable by AUTO or INTERNAL
+      * dependencies from the target object.  These should be deleted silently,
+      * even if the actual deletion pass first reaches one of them via a
+      * non-auto dependency.
+      */
+     init_object_addresses(&oktodelete);
+
+     findAutoDeletableObjects(object, &oktodelete, depRel);
+
+     /*
+      * Now invoke only step 2 of recursiveDeletion: just recurse to the
+      * stuff dependent on the given object.
+      */
+     if (!deleteDependentObjects(object, objDescription,
+                                 DROP_CASCADE, &oktodelete, depRel))
+         elog(ERROR, "Failed to drop all objects depending on %s",
+              objDescription);
+
+     /*
+      * We do not need CommandCounterIncrement here, since if step 2 did
+      * anything then each recursive call will have ended with one.
+      */
+
+     term_object_addresses(&oktodelete);
+
+     heap_close(depRel, RowExclusiveLock);
+
+     pfree(objDescription);
+ }
+
+
+ /*
   * findAutoDeletableObjects: find all objects that are reachable by AUTO or
   * INTERNAL dependency paths from the given object.  Add them all to the
   * oktodelete list.  Note that the originally given object will also be
***************
*** 475,496 ****

      /*
       * Step 2: scan pg_depend records that link to this object, showing
!      * the things that depend on it.  Recursively delete those things. (We
!      * don't delete the pg_depend records here, as the recursive call will
!      * do that.)  Note it's important to delete the dependent objects
       * before the referenced one, since the deletion routines might do
       * things like try to update the pg_class record when deleting a check
       * constraint.
-      *
-      * Again, when dropping a whole object (subId = 0), find pg_depend
-      * records for its sub-objects too.
-      *
-      * NOTE: because we are using SnapshotNow, if a recursive call deletes
-      * any pg_depend tuples that our scan hasn't yet visited, we will not
-      * see them as good when we do visit them.    This is essential for
-      * correct behavior if there are multiple dependency paths between two
-      * objects --- else we might try to delete an already-deleted object.
       */
      ScanKeyEntryInitialize(&key[0], 0x0,
                             Anum_pg_depend_refclassid, F_OIDEQ,
                             ObjectIdGetDatum(object->classId));
--- 538,627 ----

      /*
       * Step 2: scan pg_depend records that link to this object, showing
!      * the things that depend on it.  Recursively delete those things.
!      * Note it's important to delete the dependent objects
       * before the referenced one, since the deletion routines might do
       * things like try to update the pg_class record when deleting a check
       * constraint.
       */
+     if (!deleteDependentObjects(object, objDescription,
+                                 behavior, oktodelete, depRel))
+         ok = false;
+
+     /*
+      * We do not need CommandCounterIncrement here, since if step 2 did
+      * anything then each recursive call will have ended with one.
+      */
+
+     /*
+      * Step 3: delete the object itself.
+      */
+     doDeletion(object);
+
+     /*
+      * Delete any comments associated with this object.  (This is a
+      * convenient place to do it instead of having every object type know
+      * to do it.)
+      */
+     DeleteComments(object->objectId, object->classId, object->objectSubId);
+
+     /*
+      * CommandCounterIncrement here to ensure that preceding changes are
+      * all visible.
+      */
+     CommandCounterIncrement();
+
+     /*
+      * And we're done!
+      */
+     pfree(objDescription);
+
+     return ok;
+ }
+
+
+ /*
+  * deleteDependentObjects - find and delete objects that depend on 'object'
+  *
+  * Scan pg_depend records that link to the given object, showing
+  * the things that depend on it.  Recursively delete those things. (We
+  * don't delete the pg_depend records here, as the recursive call will
+  * do that.)  Note it's important to delete the dependent objects
+  * before the referenced one, since the deletion routines might do
+  * things like try to update the pg_class record when deleting a check
+  * constraint.
+  *
+  * When dropping a whole object (subId = 0), find pg_depend records for
+  * its sub-objects too.
+  *
+  *    object: the object to find dependencies on
+  *    objDescription: description of object (only used for error messages)
+  *    behavior: desired drop behavior
+  *    oktodelete: stuff that's AUTO-deletable
+  *    depRel: already opened pg_depend relation
+  *
+  * Returns TRUE if all is well, false if any problem found.
+  *
+  * NOTE: because we are using SnapshotNow, if a recursive call deletes
+  * any pg_depend tuples that our scan hasn't yet visited, we will not
+  * see them as good when we do visit them.    This is essential for
+  * correct behavior if there are multiple dependency paths between two
+  * objects --- else we might try to delete an already-deleted object.
+  */
+ static bool
+ deleteDependentObjects(const ObjectAddress *object,
+                        const char *objDescription,
+                        DropBehavior behavior,
+                        ObjectAddresses *oktodelete,
+                        Relation depRel)
+ {
+     bool        ok = true;
+     ScanKeyData key[3];
+     int            nkeys;
+     SysScanDesc scan;
+     HeapTuple    tup;
+     ObjectAddress otherObject;
+
      ScanKeyEntryInitialize(&key[0], 0x0,
                             Anum_pg_depend_refclassid, F_OIDEQ,
                             ObjectIdGetDatum(object->classId));
***************
*** 579,612 ****
      }

      systable_endscan(scan);
-
-     /*
-      * We do not need CommandCounterIncrement here, since if step 2 did
-      * anything then each recursive call will have ended with one.
-      */
-
-     /*
-      * Step 3: delete the object itself.
-      */
-     doDeletion(object);
-
-     /*
-      * Delete any comments associated with this object.  (This is a
-      * convenient place to do it instead of having every object type know
-      * to do it.)
-      */
-     DeleteComments(object->objectId, object->classId, object->objectSubId);
-
-     /*
-      * CommandCounterIncrement here to ensure that preceding changes are
-      * all visible.
-      */
-     CommandCounterIncrement();
-
-     /*
-      * And we're done!
-      */
-     pfree(objDescription);

      return ok;
  }
--- 710,715 ----
*** src/backend/catalog/namespace.c~    Sat Nov  2 13:41:21 2002
--- src/backend/catalog/namespace.c    Thu Feb  6 20:14:25 2003
***************
*** 19,33 ****
   */
  #include "postgres.h"

- #include "access/heapam.h"
  #include "access/xact.h"
- #include "catalog/catalog.h"
  #include "catalog/catname.h"
  #include "catalog/dependency.h"
- #include "catalog/heap.h"
  #include "catalog/namespace.h"
  #include "catalog/pg_conversion.h"
- #include "catalog/pg_inherits.h"
  #include "catalog/pg_namespace.h"
  #include "catalog/pg_opclass.h"
  #include "catalog/pg_operator.h"
--- 19,29 ----
***************
*** 42,51 ****
  #include "utils/acl.h"
  #include "utils/builtins.h"
  #include "utils/catcache.h"
- #include "utils/fmgroids.h"
- #include "utils/guc.h"
  #include "utils/inval.h"
  #include "utils/lsyscache.h"
  #include "utils/syscache.h"


--- 38,46 ----
  #include "utils/acl.h"
  #include "utils/builtins.h"
  #include "utils/catcache.h"
  #include "utils/inval.h"
  #include "utils/lsyscache.h"
+ #include "utils/memutils.h"
  #include "utils/syscache.h"


***************
*** 1608,1657 ****
  static void
  RemoveTempRelations(Oid tempNamespaceId)
  {
-     Relation    pgclass;
-     HeapScanDesc scan;
-     HeapTuple    tuple;
-     ScanKeyData key;
      ObjectAddress object;

      /*
!      * Scan pg_class to find all the relations in the target namespace.
!      * Ignore indexes, though, on the assumption that they'll go away when
!      * their tables are deleted.
!      *
!      * NOTE: if there are deletion constraints between temp relations, then
!      * our CASCADE delete call may cause as-yet-unvisited objects to go
!      * away.  This is okay because we are using SnapshotNow; when the scan
!      * does reach those pg_class tuples, they'll be ignored as already
!      * deleted.
       */
!     ScanKeyEntryInitialize(&key, 0x0,
!                            Anum_pg_class_relnamespace,
!                            F_OIDEQ,
!                            ObjectIdGetDatum(tempNamespaceId));
!
!     pgclass = heap_openr(RelationRelationName, AccessShareLock);
!     scan = heap_beginscan(pgclass, SnapshotNow, 1, &key);
!
!     while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
!     {
!         switch (((Form_pg_class) GETSTRUCT(tuple))->relkind)
!         {
!             case RELKIND_RELATION:
!             case RELKIND_SEQUENCE:
!             case RELKIND_VIEW:
!                 object.classId = RelOid_pg_class;
!                 object.objectId = HeapTupleGetOid(tuple);
!                 object.objectSubId = 0;
!                 performDeletion(&object, DROP_CASCADE);
!                 break;
!             default:
!                 break;
!         }
!     }

!     heap_endscan(scan);
!     heap_close(pgclass, AccessShareLock);
  }

  /*
--- 1603,1621 ----
  static void
  RemoveTempRelations(Oid tempNamespaceId)
  {
      ObjectAddress object;

      /*
!      * We want to get rid of everything in the target namespace, but not
!      * the namespace itself (deleting it only to recreate it later would be
!      * a waste of cycles).  We do this by finding everything that has a
!      * dependency on the namespace.
       */
!     object.classId = get_system_catalog_relid(NamespaceRelationName);
!     object.objectId = tempNamespaceId;
!     object.objectSubId = 0;

!     deleteWhatDependsOn(&object);
  }

  /*
*** src/include/catalog/dependency.h~    Wed Sep  4 16:31:37 2002
--- src/include/catalog/dependency.h    Thu Feb  6 20:14:25 2003
***************
*** 84,89 ****
--- 84,91 ----
  extern void performDeletion(const ObjectAddress *object,
                  DropBehavior behavior);

+ extern void deleteWhatDependsOn(const ObjectAddress *object);
+
  extern void recordDependencyOnExpr(const ObjectAddress *depender,
                         Node *expr, List *rtable,
                         DependencyType behavior);

pgsql-bugs by date:

Previous
From: Tom Lane
Date:
Subject: Re: psql 7.3.1: signal 11 + replace_vars_with_subplan_refs: variable not in subplan target list
Next
From: pgsql-bugs@postgresql.org
Date:
Subject: Bug #894: different result with the same parameterlist in function call