]> granicus.if.org Git - postgresql/commitdiff
Fix ALTER TABLE OWNER to adjust the ownership of dependent sequences,
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 23 Sep 2004 23:20:24 +0000 (23:20 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 23 Sep 2004 23:20:24 +0000 (23:20 +0000)
not only indexes.  Alvaro Herrera, with some kibitzing by Tom Lane.

src/backend/commands/tablecmds.c

index 63ee33dd3045a3103680872d4a550a6c54a88e03..c8efaa23b1ad28f9f91f16df102f04eaf9567c84 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.132 2004/09/16 16:58:28 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.133 2004/09/23 23:20:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -237,6 +237,8 @@ static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
 static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab);
 static void ATPostAlterTypeParse(char *cmd, List **wqueue);
 static void ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId);
+static void change_owner_recurse_to_sequences(Oid relationOid,
+                                                                                         int32 newOwnerSysId);
 static void ATExecClusterOn(Relation rel, const char *indexName);
 static void ATExecDropCluster(Relation rel);
 static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,
@@ -5121,8 +5123,10 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
        HeapTuple       tuple;
        Form_pg_class tuple_class;
 
-       /* Get exclusive lock till end of transaction on the target table */
-       /* Use relation_open here so that we work on indexes... */
+       /*
+        * Get exclusive lock till end of transaction on the target table.
+        * Use relation_open so that we can work on indexes and sequences.
+        */
        target_rel = relation_open(relationOid, AccessExclusiveLock);
 
        /* Get its pg_class tuple, too */
@@ -5202,8 +5206,8 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
 
                /*
                 * If we are operating on a table, also change the ownership of
-                * any indexes that belong to the table, as well as the table's
-                * toast table (if it has one)
+                * any indexes and sequences that belong to the table, as well as
+                * the table's toast table (if it has one)
                 */
                if (tuple_class->relkind == RELKIND_RELATION ||
                        tuple_class->relkind == RELKIND_TOASTVALUE)
@@ -5226,6 +5230,9 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
                        /* If it has a toast table, recurse to change its ownership */
                        if (tuple_class->reltoastrelid != InvalidOid)
                                ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerSysId);
+
+                       /* If it has dependent sequences, recurse to change them too */
+                       change_owner_recurse_to_sequences(relationOid, newOwnerSysId);
                }
        }
 
@@ -5234,6 +5241,73 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
        relation_close(target_rel, NoLock);
 }
 
+/*
+ * change_owner_recurse_to_sequences
+ *
+ * Helper function for ATExecChangeOwner.  Examines pg_depend searching
+ * for sequences that are dependent on serial columns, and changes their
+ * ownership.
+ */
+static void
+change_owner_recurse_to_sequences(Oid relationOid, int32 newOwnerSysId)
+{
+       Relation        depRel;
+       SysScanDesc scan;
+       ScanKeyData     key[2];
+       HeapTuple       tup;
+
+       /*
+        * SERIAL sequences are those having an internal dependency on one
+        * of the table's columns (we don't care *which* column, exactly).
+        */
+       depRel = heap_openr(DependRelationName, RowExclusiveLock);
+
+       ScanKeyInit(&key[0],
+                       Anum_pg_depend_refclassid,
+                       BTEqualStrategyNumber, F_OIDEQ,
+                       ObjectIdGetDatum(RelOid_pg_class));
+       ScanKeyInit(&key[1],
+                       Anum_pg_depend_refobjid,
+                       BTEqualStrategyNumber, F_OIDEQ,
+                       ObjectIdGetDatum(relationOid));
+       /* we leave refobjsubid unspecified */
+
+       scan = systable_beginscan(depRel, DependReferenceIndex, true,
+                                                         SnapshotNow, 2, key);
+
+       while (HeapTupleIsValid(tup = systable_getnext(scan)))
+       {
+               Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(tup);
+               Relation        seqRel;
+
+               /* skip dependencies other than internal dependencies on columns */
+               if (depForm->refobjsubid == 0 ||
+                       depForm->classid != RelOid_pg_class ||
+                       depForm->objsubid != 0 ||
+                       depForm->deptype != DEPENDENCY_INTERNAL)
+                       continue;
+
+               /* Use relation_open just in case it's an index */
+               seqRel = relation_open(depForm->objid, AccessExclusiveLock);
+
+               /* skip non-sequence relations */
+               if (RelationGetForm(seqRel)->relkind != RELKIND_SEQUENCE)
+               {
+                       /* No need to keep the lock */
+                       relation_close(seqRel, AccessExclusiveLock);
+                       continue;
+               }
+
+               /* We don't need to close the sequence while we alter it. */
+               ATExecChangeOwner(depForm->objid, newOwnerSysId);
+
+               /* Now we can close it.  Keep the lock till end of transaction. */
+               relation_close(seqRel, NoLock);
+       }
+
+       systable_endscan(scan);
+}
+
 /*
  * ALTER TABLE CLUSTER ON
  *