@@ -261,10 +261,10 @@ static void StoreCatalogInheritance1(Oid relationId, Oid parentOid,
261
261
int16 seqNumber , Relation inhRelation );
262
262
static int findAttrByName (const char * attributeName , List * schema );
263
263
static void AlterIndexNamespaces (Relation classRel , Relation rel ,
264
- Oid oldNspOid , Oid newNspOid );
264
+ Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved );
265
265
static 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 );
268
268
static void ATExecValidateConstraint (Relation rel , char * constrName ,
269
269
bool recurse , bool recursing , LOCKMODE lockmode );
270
270
static int transformColumnNameList (Oid relId , List * colList ,
@@ -9732,8 +9732,8 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt)
9732
9732
Oid relid ;
9733
9733
Oid oldNspOid ;
9734
9734
Oid nspOid ;
9735
- Relation classRel ;
9736
9735
RangeVar * newrv ;
9736
+ ObjectAddresses * objsMoved ;
9737
9737
9738
9738
relid = RangeVarGetRelidExtended (stmt -> relation , AccessExclusiveLock ,
9739
9739
stmt -> missing_ok , false,
@@ -9774,27 +9774,47 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt)
9774
9774
/* common checks on switching namespaces */
9775
9775
CheckSetNamespace (oldNspOid , nspOid , RelationRelationId , relid );
9776
9776
9777
+ objsMoved = new_object_addresses ();
9778
+ AlterTableNamespaceInternal (rel , oldNspOid , nspOid , objsMoved );
9779
+ free_object_addresses (objsMoved );
9780
+
9781
+ /* close rel, but keep lock until commit */
9782
+ relation_close (rel , NoLock );
9783
+ }
9784
+
9785
+ /*
9786
+ * The guts of relocating a table to another namespace: besides moving
9787
+ * the table itself, its dependent objects are relocated to the new schema.
9788
+ */
9789
+ void
9790
+ AlterTableNamespaceInternal (Relation rel , Oid oldNspOid , Oid nspOid ,
9791
+ ObjectAddresses * objsMoved )
9792
+ {
9793
+ Relation classRel ;
9794
+
9795
+ Assert (objsMoved != NULL );
9796
+
9777
9797
/* OK, modify the pg_class row and pg_depend entry */
9778
9798
classRel = heap_open (RelationRelationId , RowExclusiveLock );
9779
9799
9780
- AlterRelationNamespaceInternal (classRel , relid , oldNspOid , nspOid , true);
9800
+ AlterRelationNamespaceInternal (classRel , RelationGetRelid (rel ), oldNspOid ,
9801
+ nspOid , true, objsMoved );
9781
9802
9782
9803
/* Fix the table's row type too */
9783
- AlterTypeNamespaceInternal (rel -> rd_rel -> reltype , nspOid , false, false);
9804
+ AlterTypeNamespaceInternal (rel -> rd_rel -> reltype ,
9805
+ nspOid , false, false, objsMoved );
9784
9806
9785
9807
/* Fix other dependent stuff */
9786
9808
if (rel -> rd_rel -> relkind == RELKIND_RELATION )
9787
9809
{
9788
- AlterIndexNamespaces (classRel , rel , oldNspOid , nspOid );
9789
- AlterSeqNamespaces (classRel , rel , oldNspOid , nspOid , stmt -> newschema ,
9790
- AccessExclusiveLock );
9791
- AlterConstraintNamespaces (relid , oldNspOid , nspOid , false);
9810
+ AlterIndexNamespaces (classRel , rel , oldNspOid , nspOid , objsMoved );
9811
+ AlterSeqNamespaces (classRel , rel , oldNspOid , nspOid ,
9812
+ objsMoved , AccessExclusiveLock );
9813
+ AlterConstraintNamespaces (RelationGetRelid (rel ), oldNspOid , nspOid ,
9814
+ false, objsMoved );
9792
9815
}
9793
9816
9794
9817
heap_close (classRel , RowExclusiveLock );
9795
-
9796
- /* close rel, but keep lock until commit */
9797
- relation_close (rel , NoLock );
9798
9818
}
9799
9819
9800
9820
/*
@@ -9805,10 +9825,11 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt)
9805
9825
void
9806
9826
AlterRelationNamespaceInternal (Relation classRel , Oid relOid ,
9807
9827
Oid oldNspOid , Oid newNspOid ,
9808
- bool hasDependEntry )
9828
+ bool hasDependEntry , ObjectAddresses * objsMoved )
9809
9829
{
9810
9830
HeapTuple classTup ;
9811
9831
Form_pg_class classForm ;
9832
+ ObjectAddress thisobj ;
9812
9833
9813
9834
classTup = SearchSysCacheCopy1 (RELOID , ObjectIdGetDatum (relOid ));
9814
9835
if (!HeapTupleIsValid (classTup ))
@@ -9817,27 +9838,39 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
9817
9838
9818
9839
Assert (classForm -> relnamespace == oldNspOid );
9819
9840
9820
- /* check for duplicate name (more friendly than unique-index failure) */
9821
- if (get_relname_relid (NameStr (classForm -> relname ),
9822
- newNspOid ) != InvalidOid )
9823
- ereport (ERROR ,
9824
- (errcode (ERRCODE_DUPLICATE_TABLE ),
9825
- errmsg ("relation \"%s\" already exists in schema \"%s\"" ,
9826
- NameStr (classForm -> relname ),
9827
- get_namespace_name (newNspOid ))));
9841
+ thisobj .classId = RelationRelationId ;
9842
+ thisobj .objectId = relOid ;
9843
+ thisobj .objectSubId = 0 ;
9844
+
9845
+ /*
9846
+ * Do nothing when there's nothing to do.
9847
+ */
9848
+ if (!object_address_present (& thisobj , objsMoved ))
9849
+ {
9850
+ /* check for duplicate name (more friendly than unique-index failure) */
9851
+ if (get_relname_relid (NameStr (classForm -> relname ),
9852
+ newNspOid ) != InvalidOid )
9853
+ ereport (ERROR ,
9854
+ (errcode (ERRCODE_DUPLICATE_TABLE ),
9855
+ errmsg ("relation \"%s\" already exists in schema \"%s\"" ,
9856
+ NameStr (classForm -> relname ),
9857
+ get_namespace_name (newNspOid ))));
9828
9858
9829
- /* classTup is a copy, so OK to scribble on */
9830
- classForm -> relnamespace = newNspOid ;
9859
+ /* classTup is a copy, so OK to scribble on */
9860
+ classForm -> relnamespace = newNspOid ;
9831
9861
9832
- simple_heap_update (classRel , & classTup -> t_self , classTup );
9833
- CatalogUpdateIndexes (classRel , classTup );
9862
+ simple_heap_update (classRel , & classTup -> t_self , classTup );
9863
+ CatalogUpdateIndexes (classRel , classTup );
9834
9864
9835
- /* Update dependency on schema if caller said so */
9836
- if (hasDependEntry &&
9837
- changeDependencyFor (RelationRelationId , relOid ,
9838
- NamespaceRelationId , oldNspOid , newNspOid ) != 1 )
9839
- elog (ERROR , "failed to change schema dependency for relation \"%s\"" ,
9840
- NameStr (classForm -> relname ));
9865
+ /* Update dependency on schema if caller said so */
9866
+ if (hasDependEntry &&
9867
+ changeDependencyFor (RelationRelationId , relOid ,
9868
+ NamespaceRelationId , oldNspOid , newNspOid ) != 1 )
9869
+ elog (ERROR , "failed to change schema dependency for relation \"%s\"" ,
9870
+ NameStr (classForm -> relname ));
9871
+
9872
+ add_exact_object_address (& thisobj , objsMoved );
9873
+ }
9841
9874
9842
9875
heap_freetuple (classTup );
9843
9876
}
@@ -9850,7 +9883,7 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
9850
9883
*/
9851
9884
static void
9852
9885
AlterIndexNamespaces (Relation classRel , Relation rel ,
9853
- Oid oldNspOid , Oid newNspOid )
9886
+ Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved )
9854
9887
{
9855
9888
List * indexList ;
9856
9889
ListCell * l ;
@@ -9860,15 +9893,27 @@ AlterIndexNamespaces(Relation classRel, Relation rel,
9860
9893
foreach (l , indexList )
9861
9894
{
9862
9895
Oid indexOid = lfirst_oid (l );
9896
+ ObjectAddress thisobj ;
9897
+
9898
+ thisobj .classId = RelationRelationId ;
9899
+ thisobj .objectId = indexOid ;
9900
+ thisobj .objectSubId = 0 ;
9863
9901
9864
9902
/*
9865
9903
* Note: currently, the index will not have its own dependency on the
9866
9904
* namespace, so we don't need to do changeDependencyFor(). There's no
9867
9905
* row type in pg_type, either.
9906
+ *
9907
+ * XXX this objsMoved test may be pointless -- surely we have a single
9908
+ * dependency link from a relation to each index?
9868
9909
*/
9869
- AlterRelationNamespaceInternal (classRel , indexOid ,
9870
- oldNspOid , newNspOid ,
9871
- false);
9910
+ if (!object_address_present (& thisobj , objsMoved ))
9911
+ {
9912
+ AlterRelationNamespaceInternal (classRel , indexOid ,
9913
+ oldNspOid , newNspOid ,
9914
+ false, objsMoved );
9915
+ add_exact_object_address (& thisobj , objsMoved );
9916
+ }
9872
9917
}
9873
9918
9874
9919
list_free (indexList );
@@ -9883,7 +9928,8 @@ AlterIndexNamespaces(Relation classRel, Relation rel,
9883
9928
*/
9884
9929
static void
9885
9930
AlterSeqNamespaces (Relation classRel , Relation rel ,
9886
- Oid oldNspOid , Oid newNspOid , const char * newNspName , LOCKMODE lockmode )
9931
+ Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved ,
9932
+ LOCKMODE lockmode )
9887
9933
{
9888
9934
Relation depRel ;
9889
9935
SysScanDesc scan ;
@@ -9935,14 +9981,14 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
9935
9981
/* Fix the pg_class and pg_depend entries */
9936
9982
AlterRelationNamespaceInternal (classRel , depForm -> objid ,
9937
9983
oldNspOid , newNspOid ,
9938
- true);
9984
+ true, objsMoved );
9939
9985
9940
9986
/*
9941
9987
* Sequences have entries in pg_type. We need to be careful to move
9942
9988
* them to the new namespace, too.
9943
9989
*/
9944
9990
AlterTypeNamespaceInternal (RelationGetForm (seqRel )-> reltype ,
9945
- newNspOid , false, false);
9991
+ newNspOid , false, false, objsMoved );
9946
9992
9947
9993
/* Now we can close it. Keep the lock till end of transaction. */
9948
9994
relation_close (seqRel , NoLock );
0 commit comments