@@ -805,6 +805,104 @@ get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok)
805
805
return conOid ;
806
806
}
807
807
808
+ /*
809
+ * get_relation_constraint_attnos
810
+ * Find a constraint on the specified relation with the specified name
811
+ * and return the constrained columns.
812
+ *
813
+ * Returns a Bitmapset of the column attnos of the constrained columns, with
814
+ * attnos being offset by FirstLowInvalidHeapAttributeNumber so that system
815
+ * columns can be represented.
816
+ *
817
+ * *constraintOid is set to the OID of the constraint, or InvalidOid on
818
+ * failure.
819
+ */
820
+ Bitmapset *
821
+ get_relation_constraint_attnos (Oid relid , const char * conname ,
822
+ bool missing_ok , Oid * constraintOid )
823
+ {
824
+ Bitmapset * conattnos = NULL ;
825
+ Relation pg_constraint ;
826
+ HeapTuple tuple ;
827
+ SysScanDesc scan ;
828
+ ScanKeyData skey [1 ];
829
+
830
+ /* Set *constraintOid, to avoid complaints about uninitialized vars */
831
+ * constraintOid = InvalidOid ;
832
+
833
+ /*
834
+ * Fetch the constraint tuple from pg_constraint. There may be more than
835
+ * one match, because constraints are not required to have unique names;
836
+ * if so, error out.
837
+ */
838
+ pg_constraint = heap_open (ConstraintRelationId , AccessShareLock );
839
+
840
+ ScanKeyInit (& skey [0 ],
841
+ Anum_pg_constraint_conrelid ,
842
+ BTEqualStrategyNumber , F_OIDEQ ,
843
+ ObjectIdGetDatum (relid ));
844
+
845
+ scan = systable_beginscan (pg_constraint , ConstraintRelidIndexId , true,
846
+ NULL , 1 , skey );
847
+
848
+ while (HeapTupleIsValid (tuple = systable_getnext (scan )))
849
+ {
850
+ Form_pg_constraint con = (Form_pg_constraint ) GETSTRUCT (tuple );
851
+ Datum adatum ;
852
+ bool isNull ;
853
+ ArrayType * arr ;
854
+ int16 * attnums ;
855
+ int numcols ;
856
+ int i ;
857
+
858
+ /* Check the constraint name */
859
+ if (strcmp (NameStr (con -> conname ), conname ) != 0 )
860
+ continue ;
861
+ if (OidIsValid (* constraintOid ))
862
+ ereport (ERROR ,
863
+ (errcode (ERRCODE_DUPLICATE_OBJECT ),
864
+ errmsg ("table \"%s\" has multiple constraints named \"%s\"" ,
865
+ get_rel_name (relid ), conname )));
866
+
867
+ * constraintOid = HeapTupleGetOid (tuple );
868
+
869
+ /* Extract the conkey array, ie, attnums of constrained columns */
870
+ adatum = heap_getattr (tuple , Anum_pg_constraint_conkey ,
871
+ RelationGetDescr (pg_constraint ), & isNull );
872
+ if (isNull )
873
+ continue ; /* no constrained columns */
874
+
875
+ arr = DatumGetArrayTypeP (adatum ); /* ensure not toasted */
876
+ numcols = ARR_DIMS (arr )[0 ];
877
+ if (ARR_NDIM (arr ) != 1 ||
878
+ numcols < 0 ||
879
+ ARR_HASNULL (arr ) ||
880
+ ARR_ELEMTYPE (arr ) != INT2OID )
881
+ elog (ERROR , "conkey is not a 1-D smallint array" );
882
+ attnums = (int16 * ) ARR_DATA_PTR (arr );
883
+
884
+ /* Construct the result value */
885
+ for (i = 0 ; i < numcols ; i ++ )
886
+ {
887
+ conattnos = bms_add_member (conattnos ,
888
+ attnums [i ] - FirstLowInvalidHeapAttributeNumber );
889
+ }
890
+ }
891
+
892
+ systable_endscan (scan );
893
+
894
+ /* If no such constraint exists, complain */
895
+ if (!OidIsValid (* constraintOid ) && !missing_ok )
896
+ ereport (ERROR ,
897
+ (errcode (ERRCODE_UNDEFINED_OBJECT ),
898
+ errmsg ("constraint \"%s\" for table \"%s\" does not exist" ,
899
+ conname , get_rel_name (relid ))));
900
+
901
+ heap_close (pg_constraint , AccessShareLock );
902
+
903
+ return conattnos ;
904
+ }
905
+
808
906
/*
809
907
* get_domain_constraint_oid
810
908
* Find a constraint on the specified domain with the specified name.
0 commit comments