@ -2064,33 +2064,15 @@ SetRelationHasSubclass(Oid relationId, bool relhassubclass)
heap_close ( relationRelation , RowExclusiveLock ) ;
heap_close ( relationRelation , RowExclusiveLock ) ;
}
}
/*
/*
* renameatt_internal - workhorse for renameatt
* renameatt_check - basic sanity checks before attribute rename
*/
*/
static void
static void
renameatt_internal ( Oid myrelid ,
renameatt_check ( Oid myrelid , Form_pg_class classform , bool recursing )
const char * oldattname ,
const char * newattname ,
bool recurse ,
bool recursing ,
int expected_parents ,
DropBehavior behavior )
{
{
Relation targetrelation ;
char relkind = classform - > relkind ;
Relation attrelation ;
HeapTuple atttup ;
Form_pg_attribute attform ;
int attnum ;
char relkind ;
/*
* Grab an exclusive lock on the target table , which we will NOT release
* until end of transaction .
*/
targetrelation = relation_open ( myrelid , AccessExclusiveLock ) ;
if ( targetrelation - > rd_rel - > reloftype & & ! recursing )
if ( classform - > reloftype & & ! recursing )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
errmsg ( " cannot rename column of typed table " ) ) ) ;
errmsg ( " cannot rename column of typed table " ) ) ) ;
@ -2102,7 +2084,6 @@ renameatt_internal(Oid myrelid,
* change names that are hardcoded into the system , hence the following
* change names that are hardcoded into the system , hence the following
* restriction .
* restriction .
*/
*/
relkind = RelationGetForm ( targetrelation ) - > relkind ;
if ( relkind ! = RELKIND_RELATION & &
if ( relkind ! = RELKIND_RELATION & &
relkind ! = RELKIND_VIEW & &
relkind ! = RELKIND_VIEW & &
relkind ! = RELKIND_COMPOSITE_TYPE & &
relkind ! = RELKIND_COMPOSITE_TYPE & &
@ -2111,19 +2092,45 @@ renameatt_internal(Oid myrelid,
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
errmsg ( " \" %s \" is not a table, view, composite type, index or foreign table " ,
errmsg ( " \" %s \" is not a table, view, composite type, index or foreign table " ,
RelationGetRelationName ( targetrelation ) ) ) ) ;
NameStr ( classform - > relname ) ) ) ) ;
/*
/*
* permissions checking . only the owner of a class can change its schema .
* permissions checking . only the owner of a class can change its schema .
*/
*/
if ( ! pg_class_ownercheck ( myrelid , GetUserId ( ) ) )
if ( ! pg_class_ownercheck ( myrelid , GetUserId ( ) ) )
aclcheck_error ( ACLCHECK_NOT_OWNER , ACL_KIND_CLASS ,
aclcheck_error ( ACLCHECK_NOT_OWNER , ACL_KIND_CLASS ,
RelationGetRelationName ( targetrelation ) ) ;
NameStr ( classform - > relname ) ) ;
if ( ! allowSystemTableMods & & IsSystemRelation ( targetrelation ) )
if ( ! allowSystemTableMods & & IsSystemClass ( classform ) )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_INSUFFICIENT_PRIVILEGE ) ,
( errcode ( ERRCODE_INSUFFICIENT_PRIVILEGE ) ,
errmsg ( " permission denied: \" %s \" is a system catalog " ,
errmsg ( " permission denied: \" %s \" is a system catalog " ,
RelationGetRelationName ( targetrelation ) ) ) ) ;
NameStr ( classform - > relname ) ) ) ) ;
}
/*
* renameatt_internal - workhorse for renameatt
*/
static void
renameatt_internal ( Oid myrelid ,
const char * oldattname ,
const char * newattname ,
bool recurse ,
bool recursing ,
int expected_parents ,
DropBehavior behavior )
{
Relation targetrelation ;
Relation attrelation ;
HeapTuple atttup ;
Form_pg_attribute attform ;
int attnum ;
/*
* Grab an exclusive lock on the target table , which we will NOT release
* until end of transaction .
*/
targetrelation = relation_open ( myrelid , AccessExclusiveLock ) ;
renameatt_check ( myrelid , RelationGetForm ( targetrelation ) , recursing ) ;
/*
/*
* if the ' recurse ' flag is set then we are supposed to rename this
* if the ' recurse ' flag is set then we are supposed to rename this
@ -2252,14 +2259,38 @@ renameatt_internal(Oid myrelid,
relation_close ( targetrelation , NoLock ) ; /* close rel but keep lock */
relation_close ( targetrelation , NoLock ) ; /* close rel but keep lock */
}
}
/*
* Perform permissions and integrity checks before acquiring a relation lock .
*/
static void
RangeVarCallbackForRenameAttribute ( const RangeVar * rv , Oid relid , Oid oldrelid ,
void * arg )
{
HeapTuple tuple ;
Form_pg_class form ;
tuple = SearchSysCache1 ( RELOID , ObjectIdGetDatum ( relid ) ) ;
if ( ! HeapTupleIsValid ( tuple ) )
return ; /* concurrently dropped */
form = ( Form_pg_class ) GETSTRUCT ( tuple ) ;
renameatt_check ( relid , form , false ) ;
ReleaseSysCache ( tuple ) ;
}
/*
/*
* renameatt - changes the name of a attribute in a relation
* renameatt - changes the name of a attribute in a relation
*/
*/
void
void
renameatt ( Oid myrelid , RenameStmt * stmt )
renameatt ( RenameStmt * stmt )
{
{
renameatt_internal ( myrelid ,
Oid relid ;
/* lock level taken here should match renameatt_internal */
relid = RangeVarGetRelidExtended ( stmt - > relation , AccessExclusiveLock ,
false , false ,
RangeVarCallbackForRenameAttribute ,
NULL ) ;
renameatt_internal ( relid ,
stmt - > subname , /* old att name */
stmt - > subname , /* old att name */
stmt - > newname , /* new att name */
stmt - > newname , /* new att name */
interpretInhOption ( stmt - > relation - > inhOpt ) , /* recursive? */
interpretInhOption ( stmt - > relation - > inhOpt ) , /* recursive? */
@ -2268,29 +2299,44 @@ renameatt(Oid myrelid, RenameStmt *stmt)
stmt - > behavior ) ;
stmt - > behavior ) ;
}
}
/*
/*
* Execute ALTER TABLE / INDEX / SEQUENCE / VIEW / FOREIGN TABLE RENAME
* Perform permissions and integrity checks before acquiring a relation lock .
*
* Caller has already done permissions checks .
*/
*/
void
static void
RenameRelation ( Oid myrelid , const char * newrelname , ObjectType reltype )
RangeVarCallbackForRenameRelation ( const RangeVar * rv , Oid relid , Oid oldrelid ,
void * arg )
{
{
Relation targetrelation ;
RenameStmt * stmt = ( RenameStmt * ) arg ;
Oid namespaceId ;
ObjectType reltype ;
char relkind ;
HeapTuple tuple ;
Form_pg_class classform ;
AclResult aclresult ;
char relkind ;
/*
tuple = SearchSysCache1 ( RELOID , ObjectIdGetDatum ( relid ) ) ;
* Grab an exclusive lock on the target table , index , sequence or view ,
if ( ! HeapTupleIsValid ( tuple ) )
* which we will NOT release until end of transaction .
return ; /* concurrently dropped */
*
classform = ( Form_pg_class ) GETSTRUCT ( tuple ) ;
* Lock level used here should match ExecRenameStmt
relkind = classform - > relkind ;
*/
targetrelation = relation_open ( myrelid , AccessExclusiveLock ) ;
namespaceId = RelationGetNamespace ( targetrelation ) ;
/* Must own table. */
relkind = targetrelation - > rd_rel - > relkind ;
if ( ! pg_class_ownercheck ( relid , GetUserId ( ) ) )
aclcheck_error ( ACLCHECK_NOT_OWNER , ACL_KIND_CLASS ,
NameStr ( classform - > relname ) ) ;
/* No system table modifications unless explicitly allowed. */
if ( ! allowSystemTableMods & & IsSystemClass ( classform ) )
ereport ( ERROR ,
( errcode ( ERRCODE_INSUFFICIENT_PRIVILEGE ) ,
errmsg ( " permission denied: \" %s \" is a system catalog " ,
NameStr ( classform - > relname ) ) ) ) ;
/* Must (still) have CREATE rights on containing namespace. */
aclresult = pg_namespace_aclcheck ( classform - > relnamespace , GetUserId ( ) ,
ACL_CREATE ) ;
if ( aclresult ! = ACLCHECK_OK )
aclcheck_error ( aclresult , ACL_KIND_NAMESPACE ,
get_namespace_name ( classform - > relnamespace ) ) ;
/*
/*
* For compatibility with prior releases , we don ' t complain if ALTER TABLE
* For compatibility with prior releases , we don ' t complain if ALTER TABLE
@ -2298,23 +2344,21 @@ RenameRelation(Oid myrelid, const char *newrelname, ObjectType reltype)
* ALTER SEQUENCE / VIEW / FOREIGN TABLE are only to be used with relations of
* ALTER SEQUENCE / VIEW / FOREIGN TABLE are only to be used with relations of
* that type .
* that type .
*/
*/
reltype = stmt - > renameType ;
if ( reltype = = OBJECT_SEQUENCE & & relkind ! = RELKIND_SEQUENCE )
if ( reltype = = OBJECT_SEQUENCE & & relkind ! = RELKIND_SEQUENCE )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
errmsg ( " \" %s \" is not a sequence " ,
errmsg ( " \" %s \" is not a sequence " , rv - > relname ) ) ) ;
RelationGetRelationName ( targetrelation ) ) ) ) ;
if ( reltype = = OBJECT_VIEW & & relkind ! = RELKIND_VIEW )
if ( reltype = = OBJECT_VIEW & & relkind ! = RELKIND_VIEW )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
errmsg ( " \" %s \" is not a view " ,
errmsg ( " \" %s \" is not a view " , rv - > relname ) ) ) ;
RelationGetRelationName ( targetrelation ) ) ) ) ;
if ( reltype = = OBJECT_FOREIGN_TABLE & & relkind ! = RELKIND_FOREIGN_TABLE )
if ( reltype = = OBJECT_FOREIGN_TABLE & & relkind ! = RELKIND_FOREIGN_TABLE )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
errmsg ( " \" %s \" is not a foreign table " ,
errmsg ( " \" %s \" is not a foreign table " , rv - > relname ) ) ) ;
RelationGetRelationName ( targetrelation ) ) ) ) ;
/*
/*
* Don ' t allow ALTER TABLE on composite types . We want people to use ALTER
* Don ' t allow ALTER TABLE on composite types . We want people to use ALTER
@ -2323,17 +2367,35 @@ RenameRelation(Oid myrelid, const char *newrelname, ObjectType reltype)
if ( relkind = = RELKIND_COMPOSITE_TYPE )
if ( relkind = = RELKIND_COMPOSITE_TYPE )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
errmsg ( " \" %s \" is a composite type " ,
errmsg ( " \" %s \" is a composite type " , rv - > relname ) ,
RelationGetRelationName ( targetrelation ) ) ,
errhint ( " Use ALTER TYPE instead. " ) ) ) ;
errhint ( " Use ALTER TYPE instead. " ) ) ) ;
/* Do the work */
ReleaseSysCache ( tuple ) ;
RenameRelationInternal ( myrelid , newrelname , namespaceId ) ;
}
/*
* Execute ALTER TABLE / INDEX / SEQUENCE / VIEW / FOREIGN TABLE RENAME
*/
void
RenameRelation ( RenameStmt * stmt )
{
Oid relid ;
/*
/*
* Close rel , but keep exclusive lock !
* Grab an exclusive lock on the target table , index , sequence or view ,
* which we will NOT release until end of transaction .
*
* Lock level used here should match RenameRelationInternal , to avoid
* lock escalation .
*/
*/
relation_close ( targetrelation , NoLock ) ;
relid = RangeVarGetRelidExtended ( stmt - > relation , AccessExclusiveLock ,
false , false ,
RangeVarCallbackForRenameRelation ,
( void * ) stmt ) ;
/* Do the work */
RenameRelationInternal ( relid , stmt - > newname ) ;
}
}
/*
/*
@ -2346,18 +2408,20 @@ RenameRelation(Oid myrelid, const char *newrelname, ObjectType reltype)
* sequence , AFAIK there ' s no need for it to be there .
* sequence , AFAIK there ' s no need for it to be there .
*/
*/
void
void
RenameRelationInternal ( Oid myrelid , const char * newrelname , Oid namespaceId )
RenameRelationInternal ( Oid myrelid , const char * newrelname )
{
{
Relation targetrelation ;
Relation targetrelation ;
Relation relrelation ; /* for RELATION relation */
Relation relrelation ; /* for RELATION relation */
HeapTuple reltup ;
HeapTuple reltup ;
Form_pg_class relform ;
Form_pg_class relform ;
Oid namespaceId ;
/*
/*
* Grab an exclusive lock on the target table , index , sequence or view ,
* Grab an exclusive lock on the target table , index , sequence or view ,
* which we will NOT release until end of transaction .
* which we will NOT release until end of transaction .
*/
*/
targetrelation = relation_open ( myrelid , AccessExclusiveLock ) ;
targetrelation = relation_open ( myrelid , AccessExclusiveLock ) ;
namespaceId = RelationGetNamespace ( targetrelation ) ;
/*
/*
* Find relation ' s pg_class tuple , and make sure newrelname isn ' t in use .
* Find relation ' s pg_class tuple , and make sure newrelname isn ' t in use .
@ -5376,7 +5440,7 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
ereport ( NOTICE ,
ereport ( NOTICE ,
( errmsg ( " ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \" %s \" to \" %s \" " ,
( errmsg ( " ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \" %s \" to \" %s \" " ,
indexName , constraintName ) ) ) ;
indexName , constraintName ) ) ) ;
RenameRelation ( index_oid , constraintName , OBJECT_INDEX ) ;
RenameRelationInternal ( index_oid , constraintName ) ;
}
}
/* Extra checks needed if making primary key */
/* Extra checks needed if making primary key */