@@ -254,10 +254,10 @@ static void StoreCatalogInheritance1(Oid relationId, Oid parentOid,
254
254
static int findAttrByName (const char * attributeName , List * schema );
255
255
static void setRelhassubclassInRelation (Oid relationId , bool relhassubclass );
256
256
static void AlterIndexNamespaces (Relation classRel , Relation rel ,
257
- Oid oldNspOid , Oid newNspOid );
257
+ Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved );
258
258
static void AlterSeqNamespaces (Relation classRel , Relation rel ,
259
- Oid oldNspOid , Oid newNspOid ,
260
- const char * newNspName , LOCKMODE lockmode );
259
+ Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved ,
260
+ LOCKMODE lockmode );
261
261
static void ATExecValidateConstraint (Relation rel , char * constrName );
262
262
static int transformColumnNameList (Oid relId , List * colList ,
263
263
int16 * attnums , Oid * atttypids );
@@ -8950,7 +8950,7 @@ AlterTableNamespace(RangeVar *relation, const char *newschema,
8950
8950
Oid relid ;
8951
8951
Oid oldNspOid ;
8952
8952
Oid nspOid ;
8953
- Relation classRel ;
8953
+ ObjectAddresses * objsMoved ;
8954
8954
8955
8955
rel = relation_openrv (relation , lockmode );
8956
8956
@@ -9042,26 +9042,47 @@ AlterTableNamespace(RangeVar *relation, const char *newschema,
9042
9042
/* common checks on switching namespaces */
9043
9043
CheckSetNamespace (oldNspOid , nspOid , RelationRelationId , relid );
9044
9044
9045
+ objsMoved = new_object_addresses ();
9046
+ AlterTableNamespaceInternal (rel , oldNspOid , nspOid , objsMoved );
9047
+ free_object_addresses (objsMoved );
9048
+
9049
+ /* close rel, but keep lock until commit */
9050
+ relation_close (rel , NoLock );
9051
+ }
9052
+
9053
+ /*
9054
+ * The guts of relocating a table to another namespace: besides moving
9055
+ * the table itself, its dependent objects are relocated to the new schema.
9056
+ */
9057
+ void
9058
+ AlterTableNamespaceInternal (Relation rel , Oid oldNspOid , Oid nspOid ,
9059
+ ObjectAddresses * objsMoved )
9060
+ {
9061
+ Relation classRel ;
9062
+
9063
+ Assert (objsMoved != NULL );
9064
+
9045
9065
/* OK, modify the pg_class row and pg_depend entry */
9046
9066
classRel = heap_open (RelationRelationId , RowExclusiveLock );
9047
9067
9048
- AlterRelationNamespaceInternal (classRel , relid , oldNspOid , nspOid , true);
9068
+ AlterRelationNamespaceInternal (classRel , RelationGetRelid (rel ), oldNspOid ,
9069
+ nspOid , true, objsMoved );
9049
9070
9050
9071
/* Fix the table's row type too */
9051
- AlterTypeNamespaceInternal (rel -> rd_rel -> reltype , nspOid , false, false);
9072
+ AlterTypeNamespaceInternal (rel -> rd_rel -> reltype ,
9073
+ nspOid , false, false, objsMoved );
9052
9074
9053
9075
/* Fix other dependent stuff */
9054
9076
if (rel -> rd_rel -> relkind == RELKIND_RELATION )
9055
9077
{
9056
- AlterIndexNamespaces (classRel , rel , oldNspOid , nspOid );
9057
- AlterSeqNamespaces (classRel , rel , oldNspOid , nspOid , newschema , lockmode );
9058
- AlterConstraintNamespaces (relid , oldNspOid , nspOid , false);
9078
+ AlterIndexNamespaces (classRel , rel , oldNspOid , nspOid , objsMoved );
9079
+ AlterSeqNamespaces (classRel , rel , oldNspOid , nspOid ,
9080
+ objsMoved , AccessExclusiveLock );
9081
+ AlterConstraintNamespaces (RelationGetRelid (rel ), oldNspOid , nspOid ,
9082
+ false, objsMoved );
9059
9083
}
9060
9084
9061
9085
heap_close (classRel , RowExclusiveLock );
9062
-
9063
- /* close rel, but keep lock until commit */
9064
- relation_close (rel , NoLock );
9065
9086
}
9066
9087
9067
9088
/*
@@ -9072,10 +9093,11 @@ AlterTableNamespace(RangeVar *relation, const char *newschema,
9072
9093
void
9073
9094
AlterRelationNamespaceInternal (Relation classRel , Oid relOid ,
9074
9095
Oid oldNspOid , Oid newNspOid ,
9075
- bool hasDependEntry )
9096
+ bool hasDependEntry , ObjectAddresses * objsMoved )
9076
9097
{
9077
9098
HeapTuple classTup ;
9078
9099
Form_pg_class classForm ;
9100
+ ObjectAddress thisobj ;
9079
9101
9080
9102
classTup = SearchSysCacheCopy1 (RELOID , ObjectIdGetDatum (relOid ));
9081
9103
if (!HeapTupleIsValid (classTup ))
@@ -9084,27 +9106,39 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
9084
9106
9085
9107
Assert (classForm -> relnamespace == oldNspOid );
9086
9108
9087
- /* check for duplicate name (more friendly than unique-index failure) */
9088
- if (get_relname_relid (NameStr (classForm -> relname ),
9089
- newNspOid ) != InvalidOid )
9090
- ereport (ERROR ,
9091
- (errcode (ERRCODE_DUPLICATE_TABLE ),
9092
- errmsg ("relation \"%s\" already exists in schema \"%s\"" ,
9093
- NameStr (classForm -> relname ),
9094
- get_namespace_name (newNspOid ))));
9109
+ thisobj .classId = RelationRelationId ;
9110
+ thisobj .objectId = relOid ;
9111
+ thisobj .objectSubId = 0 ;
9112
+
9113
+ /*
9114
+ * Do nothing when there's nothing to do.
9115
+ */
9116
+ if (!object_address_present (& thisobj , objsMoved ))
9117
+ {
9118
+ /* check for duplicate name (more friendly than unique-index failure) */
9119
+ if (get_relname_relid (NameStr (classForm -> relname ),
9120
+ newNspOid ) != InvalidOid )
9121
+ ereport (ERROR ,
9122
+ (errcode (ERRCODE_DUPLICATE_TABLE ),
9123
+ errmsg ("relation \"%s\" already exists in schema \"%s\"" ,
9124
+ NameStr (classForm -> relname ),
9125
+ get_namespace_name (newNspOid ))));
9095
9126
9096
- /* classTup is a copy, so OK to scribble on */
9097
- classForm -> relnamespace = newNspOid ;
9127
+ /* classTup is a copy, so OK to scribble on */
9128
+ classForm -> relnamespace = newNspOid ;
9098
9129
9099
- simple_heap_update (classRel , & classTup -> t_self , classTup );
9100
- CatalogUpdateIndexes (classRel , classTup );
9130
+ simple_heap_update (classRel , & classTup -> t_self , classTup );
9131
+ CatalogUpdateIndexes (classRel , classTup );
9101
9132
9102
- /* Update dependency on schema if caller said so */
9103
- if (hasDependEntry &&
9104
- changeDependencyFor (RelationRelationId , relOid ,
9105
- NamespaceRelationId , oldNspOid , newNspOid ) != 1 )
9106
- elog (ERROR , "failed to change schema dependency for relation \"%s\"" ,
9107
- NameStr (classForm -> relname ));
9133
+ /* Update dependency on schema if caller said so */
9134
+ if (hasDependEntry &&
9135
+ changeDependencyFor (RelationRelationId , relOid ,
9136
+ NamespaceRelationId , oldNspOid , newNspOid ) != 1 )
9137
+ elog (ERROR , "failed to change schema dependency for relation \"%s\"" ,
9138
+ NameStr (classForm -> relname ));
9139
+
9140
+ add_exact_object_address (& thisobj , objsMoved );
9141
+ }
9108
9142
9109
9143
heap_freetuple (classTup );
9110
9144
}
@@ -9117,7 +9151,7 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
9117
9151
*/
9118
9152
static void
9119
9153
AlterIndexNamespaces (Relation classRel , Relation rel ,
9120
- Oid oldNspOid , Oid newNspOid )
9154
+ Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved )
9121
9155
{
9122
9156
List * indexList ;
9123
9157
ListCell * l ;
@@ -9127,15 +9161,27 @@ AlterIndexNamespaces(Relation classRel, Relation rel,
9127
9161
foreach (l , indexList )
9128
9162
{
9129
9163
Oid indexOid = lfirst_oid (l );
9164
+ ObjectAddress thisobj ;
9165
+
9166
+ thisobj .classId = RelationRelationId ;
9167
+ thisobj .objectId = indexOid ;
9168
+ thisobj .objectSubId = 0 ;
9130
9169
9131
9170
/*
9132
9171
* Note: currently, the index will not have its own dependency on the
9133
9172
* namespace, so we don't need to do changeDependencyFor(). There's no
9134
9173
* row type in pg_type, either.
9174
+ *
9175
+ * XXX this objsMoved test may be pointless -- surely we have a single
9176
+ * dependency link from a relation to each index?
9135
9177
*/
9136
- AlterRelationNamespaceInternal (classRel , indexOid ,
9137
- oldNspOid , newNspOid ,
9138
- false);
9178
+ if (!object_address_present (& thisobj , objsMoved ))
9179
+ {
9180
+ AlterRelationNamespaceInternal (classRel , indexOid ,
9181
+ oldNspOid , newNspOid ,
9182
+ false, objsMoved );
9183
+ add_exact_object_address (& thisobj , objsMoved );
9184
+ }
9139
9185
}
9140
9186
9141
9187
list_free (indexList );
@@ -9150,7 +9196,8 @@ AlterIndexNamespaces(Relation classRel, Relation rel,
9150
9196
*/
9151
9197
static void
9152
9198
AlterSeqNamespaces (Relation classRel , Relation rel ,
9153
- Oid oldNspOid , Oid newNspOid , const char * newNspName , LOCKMODE lockmode )
9199
+ Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved ,
9200
+ LOCKMODE lockmode )
9154
9201
{
9155
9202
Relation depRel ;
9156
9203
SysScanDesc scan ;
@@ -9202,14 +9249,14 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
9202
9249
/* Fix the pg_class and pg_depend entries */
9203
9250
AlterRelationNamespaceInternal (classRel , depForm -> objid ,
9204
9251
oldNspOid , newNspOid ,
9205
- true);
9252
+ true, objsMoved );
9206
9253
9207
9254
/*
9208
9255
* Sequences have entries in pg_type. We need to be careful to move
9209
9256
* them to the new namespace, too.
9210
9257
*/
9211
9258
AlterTypeNamespaceInternal (RelationGetForm (seqRel )-> reltype ,
9212
- newNspOid , false, false);
9259
+ newNspOid , false, false, objsMoved );
9213
9260
9214
9261
/* Now we can close it. Keep the lock till end of transaction. */
9215
9262
relation_close (seqRel , NoLock );
0 commit comments