mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-29 22:49:41 +03:00 
			
		
		
		
	Fix ALTER TABLE OWNER to adjust the ownership of dependent sequences,
not only indexes. Alvaro Herrera, with some kibitzing by Tom Lane.
This commit is contained in:
		| @@ -8,7 +8,7 @@ | |||||||
|  * |  * | ||||||
|  * |  * | ||||||
|  * IDENTIFICATION |  * 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 ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab); | ||||||
| static void ATPostAlterTypeParse(char *cmd, List **wqueue); | static void ATPostAlterTypeParse(char *cmd, List **wqueue); | ||||||
| static void ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId); | 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 ATExecClusterOn(Relation rel, const char *indexName); | ||||||
| static void ATExecDropCluster(Relation rel); | static void ATExecDropCluster(Relation rel); | ||||||
| static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, | static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, | ||||||
| @@ -5121,8 +5123,10 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId) | |||||||
| 	HeapTuple	tuple; | 	HeapTuple	tuple; | ||||||
| 	Form_pg_class tuple_class; | 	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); | 	target_rel = relation_open(relationOid, AccessExclusiveLock); | ||||||
|  |  | ||||||
| 	/* Get its pg_class tuple, too */ | 	/* 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 | 		 * 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 | 		 * any indexes and sequences that belong to the table, as well as | ||||||
| 		 * toast table (if it has one) | 		 * the table's toast table (if it has one) | ||||||
| 		 */ | 		 */ | ||||||
| 		if (tuple_class->relkind == RELKIND_RELATION || | 		if (tuple_class->relkind == RELKIND_RELATION || | ||||||
| 			tuple_class->relkind == RELKIND_TOASTVALUE) | 			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 it has a toast table, recurse to change its ownership */ | ||||||
| 			if (tuple_class->reltoastrelid != InvalidOid) | 			if (tuple_class->reltoastrelid != InvalidOid) | ||||||
| 				ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerSysId); | 				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); | 	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 |  * ALTER TABLE CLUSTER ON | ||||||
|  * |  * | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user