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