@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / catalog / pg_constraint . c , v 1.28 2005 / 11 / 22 18 : 17 : 0 8 momjian Exp $
* $ PostgreSQL : pgsql / src / backend / catalog / pg_constraint . c , v 1.29 2006 / 02 / 11 22 : 17 : 1 8 momjian Exp $
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
@ -664,3 +664,191 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
heap_close ( conRel , RowExclusiveLock ) ;
}
/*
* RenameConstraint
* Rename a single constraint record
* conId : The OID of the constraint to rename
* newName : The new name of the constraint
* implicitRename : is this an implicit rename ? If so , we will issue
* a notice about the implicit rename
* cmdName : the command that triggered the rename for the " implicitly
* renames " notice message
*/
void
RenameConstraint ( Oid conId , const char * newName ,
bool implicitRename , const char * cmdName )
{
Relation conRel ;
ScanKeyData key [ 1 ] ;
SysScanDesc scan ;
HeapTuple tup ;
NameData newNameData ;
Relation rel ;
Oid relId ;
Oid nspOid ;
Form_pg_constraint conform ;
/* before reading the tuple, lock the table it constraints in
* AccessExclusiveLock mode . Otherwise , if we read it before locking this
* table , the tuple might be changed by another transaction and our copy
* would be out of date
*/
relId = GetConstraintRelationId ( conId ) ;
if ( ! OidIsValid ( relId ) )
{
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_OBJECT ) ,
errmsg ( " constraint with OID %d does not exist " , conId ) ) ) ;
}
rel = relation_open ( relId , AccessExclusiveLock ) ;
nspOid = get_rel_namespace ( relId ) ;
conRel = heap_open ( ConstraintRelationId , RowExclusiveLock ) ;
ScanKeyInit ( & key [ 0 ] ,
ObjectIdAttributeNumber ,
BTEqualStrategyNumber , F_OIDEQ ,
ObjectIdGetDatum ( conId ) ) ;
scan = systable_beginscan ( conRel , ConstraintOidIndexId , true ,
SnapshotNow , 1 , key ) ;
if ( ! HeapTupleIsValid ( ( tup = systable_getnext ( scan ) ) ) )
{
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_OBJECT ) ,
errmsg ( " constraint with OID %d does not exist " , conId ) ) ) ;
}
conform = ( Form_pg_constraint ) GETSTRUCT ( tup ) ;
if ( ConstraintNameIsUsed ( CONSTRAINT_RELATION ,
conform - > conrelid ,
get_rel_namespace ( conform - > conrelid ) ,
newName ) )
{
ereport ( ERROR ,
( errcode ( ERRCODE_DUPLICATE_OBJECT ) ,
errmsg ( " constraint \" %s \" for relation \" %s \" already exists " ,
newName ,
RelationGetRelationName ( rel ) ) ) ) ;
}
tup = heap_copytuple ( tup ) ;
conform = ( Form_pg_constraint ) GETSTRUCT ( tup ) ;
if ( implicitRename & & cmdName )
{
ereport ( NOTICE ,
( errmsg ( " %s will implicitly rename constraint "
" \" %s \" to \" %s \" on table \" %s.%s \" " ,
cmdName ,
NameStr ( conform - > conname ) ,
newName ,
get_namespace_name ( nspOid ) ,
RelationGetRelationName ( rel ) ) ) ) ;
}
namestrcpy ( & newNameData , newName ) ;
conform - > conname = newNameData ;
simple_heap_update ( conRel , & tup - > t_self , tup ) ;
CatalogUpdateIndexes ( conRel , tup ) ;
heap_freetuple ( tup ) ;
systable_endscan ( scan ) ;
heap_close ( conRel , RowExclusiveLock ) ;
/* close relation but hold lock until end of transaction */
relation_close ( rel , NoLock ) ;
}
/* GetRelationConstraintOid
*
* Get the contraint OID by the relation Id of the relation it constraints and
* this relations ' name . We need this function in order to rename a constraint .
* This is done via " ALTER TABLE ... ALTER CONSTRAINT name " and the parser
* gives us the relation this constraint is defined on as well as the
* constraint ' s name .
*
* The function returns :
*
* - the unique OID of the constraint if the constraint could be found
* - the invalid OID if the constraint was not found
*
*/
Oid GetRelationConstraintOid ( Oid relId , const char * name )
{
Relation conRel ;
ScanKeyData key [ 1 ] ;
SysScanDesc scan ;
HeapTuple tup ;
Oid conId = InvalidOid ;
/* we don't change data, so an AccessShareLock is enough */
conRel = heap_open ( ConstraintRelationId , AccessShareLock ) ;
ScanKeyInit ( & key [ 0 ] ,
Anum_pg_constraint_conrelid ,
BTEqualStrategyNumber , F_OIDEQ ,
ObjectIdGetDatum ( relId ) ) ;
scan = systable_beginscan ( conRel , ConstraintRelidIndexId , true ,
SnapshotNow , 1 , key ) ;
while ( HeapTupleIsValid ( ( tup = systable_getnext ( scan ) ) ) )
{
Form_pg_constraint con = ( Form_pg_constraint ) GETSTRUCT ( tup ) ;
if ( pg_strcasecmp ( name , NameStr ( con - > conname ) ) = = 0 )
{
conId = HeapTupleGetOid ( tup ) ;
Assert ( OidIsValid ( conId ) ) ;
}
}
systable_endscan ( scan ) ;
heap_close ( conRel , AccessShareLock ) ;
return conId ;
}
/* GetConstraintRelationId
*
* Gets the OID of the relation where the constraint is defined on or the
* invalid OID if the constraint cannot be found .
*/
Oid GetConstraintRelationId ( Oid conId )
{
Relation conRel ;
ScanKeyData key [ 1 ] ;
SysScanDesc scan ;
HeapTuple tup ;
Oid relId = InvalidOid ;
/* we don't change data, so an AccessShareLock is enough */
conRel = heap_open ( ConstraintRelationId , AccessShareLock ) ;
ScanKeyInit ( & key [ 0 ] ,
ObjectIdAttributeNumber ,
BTEqualStrategyNumber , F_OIDEQ ,
ObjectIdGetDatum ( conId ) ) ;
scan = systable_beginscan ( conRel , ConstraintOidIndexId , true ,
SnapshotNow , 1 , key ) ;
if ( HeapTupleIsValid ( ( tup = systable_getnext ( scan ) ) ) )
{
Form_pg_constraint con = ( Form_pg_constraint ) GETSTRUCT ( tup ) ;
relId = con - > conrelid ;
Assert ( OidIsValid ( relId ) ) ;
}
systable_endscan ( scan ) ;
heap_close ( conRel , AccessShareLock ) ;
return relId ;
}