@@ -261,10 +261,10 @@ static void StoreCatalogInheritance1(Oid relationId, Oid parentOid,
261261 int16 seqNumber , Relation inhRelation );
262262static int findAttrByName (const char * attributeName , List * schema );
263263static void AlterIndexNamespaces (Relation classRel , Relation rel ,
264- Oid oldNspOid , Oid newNspOid );
264+ Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved );
265265static void AlterSeqNamespaces (Relation classRel , Relation rel ,
266- Oid oldNspOid , Oid newNspOid ,
267- const char * newNspName , LOCKMODE lockmode );
266+ Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved ,
267+ LOCKMODE lockmode );
268268static void ATExecValidateConstraint (Relation rel , char * constrName ,
269269 bool recurse , bool recursing , LOCKMODE lockmode );
270270static int transformColumnNameList (Oid relId , List * colList ,
@@ -9711,8 +9711,8 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt)
97119711 Oid relid ;
97129712 Oid oldNspOid ;
97139713 Oid nspOid ;
9714- Relation classRel ;
97159714 RangeVar * newrv ;
9715+ ObjectAddresses * objsMoved ;
97169716
97179717 relid = RangeVarGetRelidExtended (stmt -> relation , AccessExclusiveLock ,
97189718 stmt -> missing_ok , false,
@@ -9753,27 +9753,47 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt)
97539753 /* common checks on switching namespaces */
97549754 CheckSetNamespace (oldNspOid , nspOid , RelationRelationId , relid );
97559755
9756+ objsMoved = new_object_addresses ();
9757+ AlterTableNamespaceInternal (rel , oldNspOid , nspOid , objsMoved );
9758+ free_object_addresses (objsMoved );
9759+
9760+ /* close rel, but keep lock until commit */
9761+ relation_close (rel , NoLock );
9762+ }
9763+
9764+ /*
9765+ * The guts of relocating a table to another namespace: besides moving
9766+ * the table itself, its dependent objects are relocated to the new schema.
9767+ */
9768+ void
9769+ AlterTableNamespaceInternal (Relation rel , Oid oldNspOid , Oid nspOid ,
9770+ ObjectAddresses * objsMoved )
9771+ {
9772+ Relation classRel ;
9773+
9774+ Assert (objsMoved != NULL );
9775+
97569776 /* OK, modify the pg_class row and pg_depend entry */
97579777 classRel = heap_open (RelationRelationId , RowExclusiveLock );
97589778
9759- AlterRelationNamespaceInternal (classRel , relid , oldNspOid , nspOid , true);
9779+ AlterRelationNamespaceInternal (classRel , RelationGetRelid (rel ), oldNspOid ,
9780+ nspOid , true, objsMoved );
97609781
97619782 /* Fix the table's row type too */
9762- AlterTypeNamespaceInternal (rel -> rd_rel -> reltype , nspOid , false, false);
9783+ AlterTypeNamespaceInternal (rel -> rd_rel -> reltype ,
9784+ nspOid , false, false, objsMoved );
97639785
97649786 /* Fix other dependent stuff */
97659787 if (rel -> rd_rel -> relkind == RELKIND_RELATION )
97669788 {
9767- AlterIndexNamespaces (classRel , rel , oldNspOid , nspOid );
9768- AlterSeqNamespaces (classRel , rel , oldNspOid , nspOid , stmt -> newschema ,
9769- AccessExclusiveLock );
9770- AlterConstraintNamespaces (relid , oldNspOid , nspOid , false);
9789+ AlterIndexNamespaces (classRel , rel , oldNspOid , nspOid , objsMoved );
9790+ AlterSeqNamespaces (classRel , rel , oldNspOid , nspOid ,
9791+ objsMoved , AccessExclusiveLock );
9792+ AlterConstraintNamespaces (RelationGetRelid (rel ), oldNspOid , nspOid ,
9793+ false, objsMoved );
97719794 }
97729795
97739796 heap_close (classRel , RowExclusiveLock );
9774-
9775- /* close rel, but keep lock until commit */
9776- relation_close (rel , NoLock );
97779797}
97789798
97799799/*
@@ -9784,10 +9804,11 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt)
97849804void
97859805AlterRelationNamespaceInternal (Relation classRel , Oid relOid ,
97869806 Oid oldNspOid , Oid newNspOid ,
9787- bool hasDependEntry )
9807+ bool hasDependEntry , ObjectAddresses * objsMoved )
97889808{
97899809 HeapTuple classTup ;
97909810 Form_pg_class classForm ;
9811+ ObjectAddress thisobj ;
97919812
97929813 classTup = SearchSysCacheCopy1 (RELOID , ObjectIdGetDatum (relOid ));
97939814 if (!HeapTupleIsValid (classTup ))
@@ -9796,27 +9817,39 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
97969817
97979818 Assert (classForm -> relnamespace == oldNspOid );
97989819
9799- /* check for duplicate name (more friendly than unique-index failure) */
9800- if (get_relname_relid (NameStr (classForm -> relname ),
9801- newNspOid ) != InvalidOid )
9802- ereport (ERROR ,
9803- (errcode (ERRCODE_DUPLICATE_TABLE ),
9804- errmsg ("relation \"%s\" already exists in schema \"%s\"" ,
9805- NameStr (classForm -> relname ),
9806- get_namespace_name (newNspOid ))));
9820+ thisobj .classId = RelationRelationId ;
9821+ thisobj .objectId = relOid ;
9822+ thisobj .objectSubId = 0 ;
9823+
9824+ /*
9825+ * Do nothing when there's nothing to do.
9826+ */
9827+ if (!object_address_present (& thisobj , objsMoved ))
9828+ {
9829+ /* check for duplicate name (more friendly than unique-index failure) */
9830+ if (get_relname_relid (NameStr (classForm -> relname ),
9831+ newNspOid ) != InvalidOid )
9832+ ereport (ERROR ,
9833+ (errcode (ERRCODE_DUPLICATE_TABLE ),
9834+ errmsg ("relation \"%s\" already exists in schema \"%s\"" ,
9835+ NameStr (classForm -> relname ),
9836+ get_namespace_name (newNspOid ))));
98079837
9808- /* classTup is a copy, so OK to scribble on */
9809- classForm -> relnamespace = newNspOid ;
9838+ /* classTup is a copy, so OK to scribble on */
9839+ classForm -> relnamespace = newNspOid ;
98109840
9811- simple_heap_update (classRel , & classTup -> t_self , classTup );
9812- CatalogUpdateIndexes (classRel , classTup );
9841+ simple_heap_update (classRel , & classTup -> t_self , classTup );
9842+ CatalogUpdateIndexes (classRel , classTup );
98139843
9814- /* Update dependency on schema if caller said so */
9815- if (hasDependEntry &&
9816- changeDependencyFor (RelationRelationId , relOid ,
9817- NamespaceRelationId , oldNspOid , newNspOid ) != 1 )
9818- elog (ERROR , "failed to change schema dependency for relation \"%s\"" ,
9819- NameStr (classForm -> relname ));
9844+ /* Update dependency on schema if caller said so */
9845+ if (hasDependEntry &&
9846+ changeDependencyFor (RelationRelationId , relOid ,
9847+ NamespaceRelationId , oldNspOid , newNspOid ) != 1 )
9848+ elog (ERROR , "failed to change schema dependency for relation \"%s\"" ,
9849+ NameStr (classForm -> relname ));
9850+
9851+ add_exact_object_address (& thisobj , objsMoved );
9852+ }
98209853
98219854 heap_freetuple (classTup );
98229855}
@@ -9829,7 +9862,7 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
98299862 */
98309863static void
98319864AlterIndexNamespaces (Relation classRel , Relation rel ,
9832- Oid oldNspOid , Oid newNspOid )
9865+ Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved )
98339866{
98349867 List * indexList ;
98359868 ListCell * l ;
@@ -9839,15 +9872,27 @@ AlterIndexNamespaces(Relation classRel, Relation rel,
98399872 foreach (l , indexList )
98409873 {
98419874 Oid indexOid = lfirst_oid (l );
9875+ ObjectAddress thisobj ;
9876+
9877+ thisobj .classId = RelationRelationId ;
9878+ thisobj .objectId = indexOid ;
9879+ thisobj .objectSubId = 0 ;
98429880
98439881 /*
98449882 * Note: currently, the index will not have its own dependency on the
98459883 * namespace, so we don't need to do changeDependencyFor(). There's no
98469884 * row type in pg_type, either.
9885+ *
9886+ * XXX this objsMoved test may be pointless -- surely we have a single
9887+ * dependency link from a relation to each index?
98479888 */
9848- AlterRelationNamespaceInternal (classRel , indexOid ,
9849- oldNspOid , newNspOid ,
9850- false);
9889+ if (!object_address_present (& thisobj , objsMoved ))
9890+ {
9891+ AlterRelationNamespaceInternal (classRel , indexOid ,
9892+ oldNspOid , newNspOid ,
9893+ false, objsMoved );
9894+ add_exact_object_address (& thisobj , objsMoved );
9895+ }
98519896 }
98529897
98539898 list_free (indexList );
@@ -9862,7 +9907,8 @@ AlterIndexNamespaces(Relation classRel, Relation rel,
98629907 */
98639908static void
98649909AlterSeqNamespaces (Relation classRel , Relation rel ,
9865- Oid oldNspOid , Oid newNspOid , const char * newNspName , LOCKMODE lockmode )
9910+ Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved ,
9911+ LOCKMODE lockmode )
98669912{
98679913 Relation depRel ;
98689914 SysScanDesc scan ;
@@ -9914,14 +9960,14 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
99149960 /* Fix the pg_class and pg_depend entries */
99159961 AlterRelationNamespaceInternal (classRel , depForm -> objid ,
99169962 oldNspOid , newNspOid ,
9917- true);
9963+ true, objsMoved );
99189964
99199965 /*
99209966 * Sequences have entries in pg_type. We need to be careful to move
99219967 * them to the new namespace, too.
99229968 */
99239969 AlterTypeNamespaceInternal (RelationGetForm (seqRel )-> reltype ,
9924- newNspOid , false, false);
9970+ newNspOid , false, false, objsMoved );
99259971
99269972 /* Now we can close it. Keep the lock till end of transaction. */
99279973 relation_close (seqRel , NoLock );
0 commit comments