@ -805,6 +805,104 @@ get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok)
return conOid ;
}
/*
* get_relation_constraint_attnos
* Find a constraint on the specified relation with the specified name
* and return the constrained columns .
*
* Returns a Bitmapset of the column attnos of the constrained columns , with
* attnos being offset by FirstLowInvalidHeapAttributeNumber so that system
* columns can be represented .
*
* * constraintOid is set to the OID of the constraint , or InvalidOid on
* failure .
*/
Bitmapset *
get_relation_constraint_attnos ( Oid relid , const char * conname ,
bool missing_ok , Oid * constraintOid )
{
Bitmapset * conattnos = NULL ;
Relation pg_constraint ;
HeapTuple tuple ;
SysScanDesc scan ;
ScanKeyData skey [ 1 ] ;
/* Set *constraintOid, to avoid complaints about uninitialized vars */
* constraintOid = InvalidOid ;
/*
* Fetch the constraint tuple from pg_constraint . There may be more than
* one match , because constraints are not required to have unique names ;
* if so , error out .
*/
pg_constraint = heap_open ( ConstraintRelationId , AccessShareLock ) ;
ScanKeyInit ( & skey [ 0 ] ,
Anum_pg_constraint_conrelid ,
BTEqualStrategyNumber , F_OIDEQ ,
ObjectIdGetDatum ( relid ) ) ;
scan = systable_beginscan ( pg_constraint , ConstraintRelidIndexId , true ,
NULL , 1 , skey ) ;
while ( HeapTupleIsValid ( tuple = systable_getnext ( scan ) ) )
{
Form_pg_constraint con = ( Form_pg_constraint ) GETSTRUCT ( tuple ) ;
Datum adatum ;
bool isNull ;
ArrayType * arr ;
int16 * attnums ;
int numcols ;
int i ;
/* Check the constraint name */
if ( strcmp ( NameStr ( con - > conname ) , conname ) ! = 0 )
continue ;
if ( OidIsValid ( * constraintOid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DUPLICATE_OBJECT ) ,
errmsg ( " table \" %s \" has multiple constraints named \" %s \" " ,
get_rel_name ( relid ) , conname ) ) ) ;
* constraintOid = HeapTupleGetOid ( tuple ) ;
/* Extract the conkey array, ie, attnums of constrained columns */
adatum = heap_getattr ( tuple , Anum_pg_constraint_conkey ,
RelationGetDescr ( pg_constraint ) , & isNull ) ;
if ( isNull )
continue ; /* no constrained columns */
arr = DatumGetArrayTypeP ( adatum ) ; /* ensure not toasted */
numcols = ARR_DIMS ( arr ) [ 0 ] ;
if ( ARR_NDIM ( arr ) ! = 1 | |
numcols < 0 | |
ARR_HASNULL ( arr ) | |
ARR_ELEMTYPE ( arr ) ! = INT2OID )
elog ( ERROR , " conkey is not a 1-D smallint array " ) ;
attnums = ( int16 * ) ARR_DATA_PTR ( arr ) ;
/* Construct the result value */
for ( i = 0 ; i < numcols ; i + + )
{
conattnos = bms_add_member ( conattnos ,
attnums [ i ] - FirstLowInvalidHeapAttributeNumber ) ;
}
}
systable_endscan ( scan ) ;
/* If no such constraint exists, complain */
if ( ! OidIsValid ( * constraintOid ) & & ! missing_ok )
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_OBJECT ) ,
errmsg ( " constraint \" %s \" for table \" %s \" does not exist " ,
conname , get_rel_name ( relid ) ) ) ) ;
heap_close ( pg_constraint , AccessShareLock ) ;
return conattnos ;
}
/*
* get_domain_constraint_oid
* Find a constraint on the specified domain with the specified name .