@ -261,10 +261,10 @@ static void StoreCatalogInheritance1(Oid relationId, Oid parentOid,
int16 seqNumber , Relation inhRelation ) ;
static int findAttrByName ( const char * attributeName , List * schema ) ;
static void AlterIndexNamespaces ( Relation classRel , Relation rel ,
Oid oldNspOid , Oid newNspOid ) ;
Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved ) ;
static void AlterSeqNamespaces ( Relation classRel , Relation rel ,
Oid oldNspOid , Oid newNspOid ,
const char * newNspName , LOCKMODE lockmode ) ;
Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved ,
LOCKMODE lockmode ) ;
static void ATExecValidateConstraint ( Relation rel , char * constrName ,
bool recurse , bool recursing , LOCKMODE lockmode ) ;
static int transformColumnNameList ( Oid relId , List * colList ,
@ -9711,8 +9711,8 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt)
Oid relid ;
Oid oldNspOid ;
Oid nspOid ;
Relation classRel ;
RangeVar * newrv ;
ObjectAddresses * objsMoved ;
relid = RangeVarGetRelidExtended ( stmt - > relation , AccessExclusiveLock ,
stmt - > missing_ok , false ,
@ -9753,27 +9753,47 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt)
/* common checks on switching namespaces */
CheckSetNamespace ( oldNspOid , nspOid , RelationRelationId , relid ) ;
objsMoved = new_object_addresses ( ) ;
AlterTableNamespaceInternal ( rel , oldNspOid , nspOid , objsMoved ) ;
free_object_addresses ( objsMoved ) ;
/* close rel, but keep lock until commit */
relation_close ( rel , NoLock ) ;
}
/*
* The guts of relocating a table to another namespace : besides moving
* the table itself , its dependent objects are relocated to the new schema .
*/
void
AlterTableNamespaceInternal ( Relation rel , Oid oldNspOid , Oid nspOid ,
ObjectAddresses * objsMoved )
{
Relation classRel ;
Assert ( objsMoved ! = NULL ) ;
/* OK, modify the pg_class row and pg_depend entry */
classRel = heap_open ( RelationRelationId , RowExclusiveLock ) ;
AlterRelationNamespaceInternal ( classRel , relid , oldNspOid , nspOid , true ) ;
AlterRelationNamespaceInternal ( classRel , RelationGetRelid ( rel ) , oldNspOid ,
nspOid , true , objsMoved ) ;
/* Fix the table's row type too */
AlterTypeNamespaceInternal ( rel - > rd_rel - > reltype , nspOid , false , false ) ;
AlterTypeNamespaceInternal ( rel - > rd_rel - > reltype ,
nspOid , false , false , objsMoved ) ;
/* Fix other dependent stuff */
if ( rel - > rd_rel - > relkind = = RELKIND_RELATION )
{
AlterIndexNamespaces ( classRel , rel , oldNspOid , nspOid ) ;
AlterSeqNamespaces ( classRel , rel , oldNspOid , nspOid , stmt - > newschema ,
AccessExclusiveLock ) ;
AlterConstraintNamespaces ( relid , oldNspOid , nspOid , false ) ;
AlterIndexNamespaces ( classRel , rel , oldNspOid , nspOid , objsMoved ) ;
AlterSeqNamespaces ( classRel , rel , oldNspOid , nspOid ,
objsMoved , AccessExclusiveLock ) ;
AlterConstraintNamespaces ( RelationGetRelid ( rel ) , oldNspOid , nspOid ,
false , objsMoved ) ;
}
heap_close ( classRel , RowExclusiveLock ) ;
/* close rel, but keep lock until commit */
relation_close ( rel , NoLock ) ;
}
/*
@ -9784,10 +9804,11 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt)
void
AlterRelationNamespaceInternal ( Relation classRel , Oid relOid ,
Oid oldNspOid , Oid newNspOid ,
bool hasDependEntry )
bool hasDependEntry , ObjectAddresses * objsMoved )
{
HeapTuple classTup ;
Form_pg_class classForm ;
ObjectAddress thisobj ;
classTup = SearchSysCacheCopy1 ( RELOID , ObjectIdGetDatum ( relOid ) ) ;
if ( ! HeapTupleIsValid ( classTup ) )
@ -9796,27 +9817,39 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
Assert ( classForm - > relnamespace = = oldNspOid ) ;
/* check for duplicate name (more friendly than unique-index failure) */
if ( get_relname_relid ( NameStr ( classForm - > relname ) ,
newNspOid ) ! = InvalidOid )
ereport ( ERROR ,
( errcode ( ERRCODE_DUPLICATE_TABLE ) ,
errmsg ( " relation \" %s \" already exists in schema \" %s \" " ,
NameStr ( classForm - > relname ) ,
get_namespace_name ( newNspOid ) ) ) ) ;
thisobj . classId = RelationRelationId ;
thisobj . objectId = relOid ;
thisobj . objectSubId = 0 ;
/*
* Do nothing when there ' s nothing to do .
*/
if ( ! object_address_present ( & thisobj , objsMoved ) )
{
/* check for duplicate name (more friendly than unique-index failure) */
if ( get_relname_relid ( NameStr ( classForm - > relname ) ,
newNspOid ) ! = InvalidOid )
ereport ( ERROR ,
( errcode ( ERRCODE_DUPLICATE_TABLE ) ,
errmsg ( " relation \" %s \" already exists in schema \" %s \" " ,
NameStr ( classForm - > relname ) ,
get_namespace_name ( newNspOid ) ) ) ) ;
/* classTup is a copy, so OK to scribble on */
classForm - > relnamespace = newNspOid ;
/* classTup is a copy, so OK to scribble on */
classForm - > relnamespace = newNspOid ;
simple_heap_update ( classRel , & classTup - > t_self , classTup ) ;
CatalogUpdateIndexes ( classRel , classTup ) ;
simple_heap_update ( classRel , & classTup - > t_self , classTup ) ;
CatalogUpdateIndexes ( classRel , classTup ) ;
/* Update dependency on schema if caller said so */
if ( hasDependEntry & &
changeDependencyFor ( RelationRelationId , relOid ,
NamespaceRelationId , oldNspOid , newNspOid ) ! = 1 )
elog ( ERROR , " failed to change schema dependency for relation \" %s \" " ,
NameStr ( classForm - > relname ) ) ;
/* Update dependency on schema if caller said so */
if ( hasDependEntry & &
changeDependencyFor ( RelationRelationId , relOid ,
NamespaceRelationId , oldNspOid , newNspOid ) ! = 1 )
elog ( ERROR , " failed to change schema dependency for relation \" %s \" " ,
NameStr ( classForm - > relname ) ) ;
add_exact_object_address ( & thisobj , objsMoved ) ;
}
heap_freetuple ( classTup ) ;
}
@ -9829,7 +9862,7 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
*/
static void
AlterIndexNamespaces ( Relation classRel , Relation rel ,
Oid oldNspOid , Oid newNspOid )
Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved )
{
List * indexList ;
ListCell * l ;
@ -9839,15 +9872,27 @@ AlterIndexNamespaces(Relation classRel, Relation rel,
foreach ( l , indexList )
{
Oid indexOid = lfirst_oid ( l ) ;
ObjectAddress thisobj ;
thisobj . classId = RelationRelationId ;
thisobj . objectId = indexOid ;
thisobj . objectSubId = 0 ;
/*
* Note : currently , the index will not have its own dependency on the
* namespace , so we don ' t need to do changeDependencyFor ( ) . There ' s no
* row type in pg_type , either .
*
* XXX this objsMoved test may be pointless - - surely we have a single
* dependency link from a relation to each index ?
*/
AlterRelationNamespaceInternal ( classRel , indexOid ,
oldNspOid , newNspOid ,
false ) ;
if ( ! object_address_present ( & thisobj , objsMoved ) )
{
AlterRelationNamespaceInternal ( classRel , indexOid ,
oldNspOid , newNspOid ,
false , objsMoved ) ;
add_exact_object_address ( & thisobj , objsMoved ) ;
}
}
list_free ( indexList ) ;
@ -9862,7 +9907,8 @@ AlterIndexNamespaces(Relation classRel, Relation rel,
*/
static void
AlterSeqNamespaces ( Relation classRel , Relation rel ,
Oid oldNspOid , Oid newNspOid , const char * newNspName , LOCKMODE lockmode )
Oid oldNspOid , Oid newNspOid , ObjectAddresses * objsMoved ,
LOCKMODE lockmode )
{
Relation depRel ;
SysScanDesc scan ;
@ -9914,14 +9960,14 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
/* Fix the pg_class and pg_depend entries */
AlterRelationNamespaceInternal ( classRel , depForm - > objid ,
oldNspOid , newNspOid ,
true ) ;
true , objsMoved ) ;
/*
* Sequences have entries in pg_type . We need to be careful to move
* them to the new namespace , too .
*/
AlterTypeNamespaceInternal ( RelationGetForm ( seqRel ) - > reltype ,
newNspOid , false , false ) ;
newNspOid , false , false , objsMoved ) ;
/* Now we can close it. Keep the lock till end of transaction. */
relation_close ( seqRel , NoLock ) ;