@@ -450,14 +450,11 @@ static void
450450clone_fk_constraints (Relation pg_constraint ,Relation parentRel ,
451451Relation partRel ,List * clone ,List * * cloned )
452452{
453- TupleDesc tupdesc ;
454453AttrNumber * attmap ;
455454List * partFKs ;
456455List * subclone = NIL ;
457456ListCell * cell ;
458457
459- tupdesc = RelationGetDescr (pg_constraint );
460-
461458/*
462459 * The constraint key may differ, if the columns in the partition are
463460 * different. This map is used to convert them.
@@ -487,9 +484,6 @@ clone_fk_constraints(Relation pg_constraint, Relation parentRel,
487484int nelem ;
488485ListCell * cell ;
489486int i ;
490- ArrayType * arr ;
491- Datum datum ;
492- bool isnull ;
493487
494488tuple = SearchSysCache1 (CONSTROID ,parentConstrOid );
495489if (!tuple )
@@ -506,93 +500,11 @@ clone_fk_constraints(Relation pg_constraint, Relation parentRel,
506500
507501ObjectAddressSet (parentAddr ,ConstraintRelationId ,parentConstrOid );
508502
509- datum = fastgetattr (tuple ,Anum_pg_constraint_conkey ,
510- tupdesc ,& isnull );
511- if (isnull )
512- elog (ERROR ,"null conkey" );
513- arr = DatumGetArrayTypeP (datum );
514- nelem = ARR_DIMS (arr )[0 ];
515- if (ARR_NDIM (arr )!= 1 ||
516- nelem < 1 ||
517- nelem > INDEX_MAX_KEYS ||
518- ARR_HASNULL (arr )||
519- ARR_ELEMTYPE (arr )!= INT2OID )
520- elog (ERROR ,"conkey is not a 1-D smallint array" );
521- memcpy (conkey ,ARR_DATA_PTR (arr ),nelem * sizeof (AttrNumber ));
522-
503+ DeconstructFkConstraintRow (tuple ,& nelem ,conkey ,confkey ,
504+ conpfeqop ,conppeqop ,conffeqop );
523505for (i = 0 ;i < nelem ;i ++ )
524506mapped_conkey [i ]= attmap [conkey [i ]- 1 ];
525507
526- datum = fastgetattr (tuple ,Anum_pg_constraint_confkey ,
527- tupdesc ,& isnull );
528- if (isnull )
529- elog (ERROR ,"null confkey" );
530- arr = DatumGetArrayTypeP (datum );
531- nelem = ARR_DIMS (arr )[0 ];
532- if (ARR_NDIM (arr )!= 1 ||
533- nelem < 1 ||
534- nelem > INDEX_MAX_KEYS ||
535- ARR_HASNULL (arr )||
536- ARR_ELEMTYPE (arr )!= INT2OID )
537- elog (ERROR ,"confkey is not a 1-D smallint array" );
538- memcpy (confkey ,ARR_DATA_PTR (arr ),nelem * sizeof (AttrNumber ));
539-
540- datum = fastgetattr (tuple ,Anum_pg_constraint_conpfeqop ,
541- tupdesc ,& isnull );
542- if (isnull )
543- elog (ERROR ,"null conpfeqop" );
544- arr = DatumGetArrayTypeP (datum );
545- nelem = ARR_DIMS (arr )[0 ];
546- if (ARR_NDIM (arr )!= 1 ||
547- nelem < 1 ||
548- nelem > INDEX_MAX_KEYS ||
549- ARR_HASNULL (arr )||
550- ARR_ELEMTYPE (arr )!= OIDOID )
551- elog (ERROR ,"conpfeqop is not a 1-D OID array" );
552- memcpy (conpfeqop ,ARR_DATA_PTR (arr ),nelem * sizeof (Oid ));
553-
554- datum = fastgetattr (tuple ,Anum_pg_constraint_conpfeqop ,
555- tupdesc ,& isnull );
556- if (isnull )
557- elog (ERROR ,"null conpfeqop" );
558- arr = DatumGetArrayTypeP (datum );
559- nelem = ARR_DIMS (arr )[0 ];
560- if (ARR_NDIM (arr )!= 1 ||
561- nelem < 1 ||
562- nelem > INDEX_MAX_KEYS ||
563- ARR_HASNULL (arr )||
564- ARR_ELEMTYPE (arr )!= OIDOID )
565- elog (ERROR ,"conpfeqop is not a 1-D OID array" );
566- memcpy (conpfeqop ,ARR_DATA_PTR (arr ),nelem * sizeof (Oid ));
567-
568- datum = fastgetattr (tuple ,Anum_pg_constraint_conppeqop ,
569- tupdesc ,& isnull );
570- if (isnull )
571- elog (ERROR ,"null conppeqop" );
572- arr = DatumGetArrayTypeP (datum );
573- nelem = ARR_DIMS (arr )[0 ];
574- if (ARR_NDIM (arr )!= 1 ||
575- nelem < 1 ||
576- nelem > INDEX_MAX_KEYS ||
577- ARR_HASNULL (arr )||
578- ARR_ELEMTYPE (arr )!= OIDOID )
579- elog (ERROR ,"conppeqop is not a 1-D OID array" );
580- memcpy (conppeqop ,ARR_DATA_PTR (arr ),nelem * sizeof (Oid ));
581-
582- datum = fastgetattr (tuple ,Anum_pg_constraint_conffeqop ,
583- tupdesc ,& isnull );
584- if (isnull )
585- elog (ERROR ,"null conffeqop" );
586- arr = DatumGetArrayTypeP (datum );
587- nelem = ARR_DIMS (arr )[0 ];
588- if (ARR_NDIM (arr )!= 1 ||
589- nelem < 1 ||
590- nelem > INDEX_MAX_KEYS ||
591- ARR_HASNULL (arr )||
592- ARR_ELEMTYPE (arr )!= OIDOID )
593- elog (ERROR ,"conffeqop is not a 1-D OID array" );
594- memcpy (conffeqop ,ARR_DATA_PTR (arr ),nelem * sizeof (Oid ));
595-
596508/*
597509 * Before creating a new constraint, see whether any existing FKs are
598510 * fit for the purpose. If one is, attach the parent constraint to it,
@@ -1536,6 +1448,113 @@ get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
15361448return pkattnos ;
15371449}
15381450
1451+ /*
1452+ * Extract data from the pg_constraint tuple of a foreign-key constraint.
1453+ *
1454+ * All arguments save the first are output arguments; the last three of them
1455+ * can be passed as NULL if caller doesn't need them.
1456+ */
1457+ void
1458+ DeconstructFkConstraintRow (HeapTuple tuple ,int * numfks ,
1459+ AttrNumber * conkey ,AttrNumber * confkey ,
1460+ Oid * pf_eq_oprs ,Oid * pp_eq_oprs ,Oid * ff_eq_oprs )
1461+ {
1462+ Oid constrId = HeapTupleGetOid (tuple );
1463+ Datum adatum ;
1464+ bool isNull ;
1465+ ArrayType * arr ;
1466+ int numkeys ;
1467+
1468+ /*
1469+ * We expect the arrays to be 1-D arrays of the right types; verify that.
1470+ * We don't need to use deconstruct_array() since the array data is just
1471+ * going to look like a C array of values.
1472+ */
1473+ adatum = SysCacheGetAttr (CONSTROID ,tuple ,
1474+ Anum_pg_constraint_conkey ,& isNull );
1475+ if (isNull )
1476+ elog (ERROR ,"null conkey for constraint %u" ,constrId );
1477+ arr = DatumGetArrayTypeP (adatum );/* ensure not toasted */
1478+ if (ARR_NDIM (arr )!= 1 ||
1479+ ARR_HASNULL (arr )||
1480+ ARR_ELEMTYPE (arr )!= INT2OID )
1481+ elog (ERROR ,"conkey is not a 1-D smallint array" );
1482+ numkeys = ARR_DIMS (arr )[0 ];
1483+ if (numkeys <=0 || numkeys > INDEX_MAX_KEYS )
1484+ elog (ERROR ,"foreign key constraint cannot have %d columns" ,numkeys );
1485+ memcpy (conkey ,ARR_DATA_PTR (arr ),numkeys * sizeof (int16 ));
1486+ if ((Pointer )arr != DatumGetPointer (adatum ))
1487+ pfree (arr );/* free de-toasted copy, if any */
1488+
1489+ adatum = SysCacheGetAttr (CONSTROID ,tuple ,
1490+ Anum_pg_constraint_confkey ,& isNull );
1491+ if (isNull )
1492+ elog (ERROR ,"null confkey for constraint %u" ,constrId );
1493+ arr = DatumGetArrayTypeP (adatum );/* ensure not toasted */
1494+ if (ARR_NDIM (arr )!= 1 ||
1495+ ARR_DIMS (arr )[0 ]!= numkeys ||
1496+ ARR_HASNULL (arr )||
1497+ ARR_ELEMTYPE (arr )!= INT2OID )
1498+ elog (ERROR ,"confkey is not a 1-D smallint array" );
1499+ memcpy (confkey ,ARR_DATA_PTR (arr ),numkeys * sizeof (int16 ));
1500+ if ((Pointer )arr != DatumGetPointer (adatum ))
1501+ pfree (arr );/* free de-toasted copy, if any */
1502+
1503+ if (pf_eq_oprs )
1504+ {
1505+ adatum = SysCacheGetAttr (CONSTROID ,tuple ,
1506+ Anum_pg_constraint_conpfeqop ,& isNull );
1507+ if (isNull )
1508+ elog (ERROR ,"null conpfeqop for constraint %u" ,constrId );
1509+ arr = DatumGetArrayTypeP (adatum );/* ensure not toasted */
1510+ /* see TryReuseForeignKey if you change the test below */
1511+ if (ARR_NDIM (arr )!= 1 ||
1512+ ARR_DIMS (arr )[0 ]!= numkeys ||
1513+ ARR_HASNULL (arr )||
1514+ ARR_ELEMTYPE (arr )!= OIDOID )
1515+ elog (ERROR ,"conpfeqop is not a 1-D Oid array" );
1516+ memcpy (pf_eq_oprs ,ARR_DATA_PTR (arr ),numkeys * sizeof (Oid ));
1517+ if ((Pointer )arr != DatumGetPointer (adatum ))
1518+ pfree (arr );/* free de-toasted copy, if any */
1519+ }
1520+
1521+ if (pp_eq_oprs )
1522+ {
1523+ adatum = SysCacheGetAttr (CONSTROID ,tuple ,
1524+ Anum_pg_constraint_conppeqop ,& isNull );
1525+ if (isNull )
1526+ elog (ERROR ,"null conppeqop for constraint %u" ,constrId );
1527+ arr = DatumGetArrayTypeP (adatum );/* ensure not toasted */
1528+ if (ARR_NDIM (arr )!= 1 ||
1529+ ARR_DIMS (arr )[0 ]!= numkeys ||
1530+ ARR_HASNULL (arr )||
1531+ ARR_ELEMTYPE (arr )!= OIDOID )
1532+ elog (ERROR ,"conppeqop is not a 1-D Oid array" );
1533+ memcpy (pp_eq_oprs ,ARR_DATA_PTR (arr ),numkeys * sizeof (Oid ));
1534+ if ((Pointer )arr != DatumGetPointer (adatum ))
1535+ pfree (arr );/* free de-toasted copy, if any */
1536+ }
1537+
1538+ if (ff_eq_oprs )
1539+ {
1540+ adatum = SysCacheGetAttr (CONSTROID ,tuple ,
1541+ Anum_pg_constraint_conffeqop ,& isNull );
1542+ if (isNull )
1543+ elog (ERROR ,"null conffeqop for constraint %u" ,constrId );
1544+ arr = DatumGetArrayTypeP (adatum );/* ensure not toasted */
1545+ if (ARR_NDIM (arr )!= 1 ||
1546+ ARR_DIMS (arr )[0 ]!= numkeys ||
1547+ ARR_HASNULL (arr )||
1548+ ARR_ELEMTYPE (arr )!= OIDOID )
1549+ elog (ERROR ,"conffeqop is not a 1-D Oid array" );
1550+ memcpy (ff_eq_oprs ,ARR_DATA_PTR (arr ),numkeys * sizeof (Oid ));
1551+ if ((Pointer )arr != DatumGetPointer (adatum ))
1552+ pfree (arr );/* free de-toasted copy, if any */
1553+ }
1554+
1555+ * numfks = numkeys ;
1556+ }
1557+
15391558/*
15401559 * Determine whether a relation can be proven functionally dependent on
15411560 * a set of grouping columns. If so, return true and add the pg_constraint