@@ -446,14 +446,11 @@ static void
446446clone_fk_constraints (Relation pg_constraint , Relation parentRel ,
447447 Relation partRel , List * clone , List * * cloned )
448448{
449- TupleDesc tupdesc ;
450449 AttrNumber * attmap ;
451450 List * partFKs ;
452451 List * subclone = NIL ;
453452 ListCell * cell ;
454453
455- tupdesc = RelationGetDescr (pg_constraint );
456-
457454 /*
458455 * The constraint key may differ, if the columns in the partition are
459456 * different. This map is used to convert them.
@@ -483,9 +480,6 @@ clone_fk_constraints(Relation pg_constraint, Relation parentRel,
483480 int nelem ;
484481 ListCell * cell ;
485482 int i ;
486- ArrayType * arr ;
487- Datum datum ;
488- bool isnull ;
489483
490484 tuple = SearchSysCache1 (CONSTROID , parentConstrOid );
491485 if (!tuple )
@@ -502,93 +496,11 @@ clone_fk_constraints(Relation pg_constraint, Relation parentRel,
502496
503497 ObjectAddressSet (parentAddr , ConstraintRelationId , parentConstrOid );
504498
505- datum = fastgetattr (tuple , Anum_pg_constraint_conkey ,
506- tupdesc , & isnull );
507- if (isnull )
508- elog (ERROR , "null conkey" );
509- arr = DatumGetArrayTypeP (datum );
510- nelem = ARR_DIMS (arr )[0 ];
511- if (ARR_NDIM (arr ) != 1 ||
512- nelem < 1 ||
513- nelem > INDEX_MAX_KEYS ||
514- ARR_HASNULL (arr ) ||
515- ARR_ELEMTYPE (arr ) != INT2OID )
516- elog (ERROR , "conkey is not a 1-D smallint array" );
517- memcpy (conkey , ARR_DATA_PTR (arr ), nelem * sizeof (AttrNumber ));
518-
499+ DeconstructFkConstraintRow (tuple , & nelem , conkey , confkey ,
500+ conpfeqop , conppeqop , conffeqop );
519501 for (i = 0 ; i < nelem ; i ++ )
520502 mapped_conkey [i ] = attmap [conkey [i ] - 1 ];
521503
522- datum = fastgetattr (tuple , Anum_pg_constraint_confkey ,
523- tupdesc , & isnull );
524- if (isnull )
525- elog (ERROR , "null confkey" );
526- arr = DatumGetArrayTypeP (datum );
527- nelem = ARR_DIMS (arr )[0 ];
528- if (ARR_NDIM (arr ) != 1 ||
529- nelem < 1 ||
530- nelem > INDEX_MAX_KEYS ||
531- ARR_HASNULL (arr ) ||
532- ARR_ELEMTYPE (arr ) != INT2OID )
533- elog (ERROR , "confkey is not a 1-D smallint array" );
534- memcpy (confkey , ARR_DATA_PTR (arr ), nelem * sizeof (AttrNumber ));
535-
536- datum = fastgetattr (tuple , Anum_pg_constraint_conpfeqop ,
537- tupdesc , & isnull );
538- if (isnull )
539- elog (ERROR , "null conpfeqop" );
540- arr = DatumGetArrayTypeP (datum );
541- nelem = ARR_DIMS (arr )[0 ];
542- if (ARR_NDIM (arr ) != 1 ||
543- nelem < 1 ||
544- nelem > INDEX_MAX_KEYS ||
545- ARR_HASNULL (arr ) ||
546- ARR_ELEMTYPE (arr ) != OIDOID )
547- elog (ERROR , "conpfeqop is not a 1-D OID array" );
548- memcpy (conpfeqop , ARR_DATA_PTR (arr ), nelem * sizeof (Oid ));
549-
550- datum = fastgetattr (tuple , Anum_pg_constraint_conpfeqop ,
551- tupdesc , & isnull );
552- if (isnull )
553- elog (ERROR , "null conpfeqop" );
554- arr = DatumGetArrayTypeP (datum );
555- nelem = ARR_DIMS (arr )[0 ];
556- if (ARR_NDIM (arr ) != 1 ||
557- nelem < 1 ||
558- nelem > INDEX_MAX_KEYS ||
559- ARR_HASNULL (arr ) ||
560- ARR_ELEMTYPE (arr ) != OIDOID )
561- elog (ERROR , "conpfeqop is not a 1-D OID array" );
562- memcpy (conpfeqop , ARR_DATA_PTR (arr ), nelem * sizeof (Oid ));
563-
564- datum = fastgetattr (tuple , Anum_pg_constraint_conppeqop ,
565- tupdesc , & isnull );
566- if (isnull )
567- elog (ERROR , "null conppeqop" );
568- arr = DatumGetArrayTypeP (datum );
569- nelem = ARR_DIMS (arr )[0 ];
570- if (ARR_NDIM (arr ) != 1 ||
571- nelem < 1 ||
572- nelem > INDEX_MAX_KEYS ||
573- ARR_HASNULL (arr ) ||
574- ARR_ELEMTYPE (arr ) != OIDOID )
575- elog (ERROR , "conppeqop is not a 1-D OID array" );
576- memcpy (conppeqop , ARR_DATA_PTR (arr ), nelem * sizeof (Oid ));
577-
578- datum = fastgetattr (tuple , Anum_pg_constraint_conffeqop ,
579- tupdesc , & isnull );
580- if (isnull )
581- elog (ERROR , "null conffeqop" );
582- arr = DatumGetArrayTypeP (datum );
583- nelem = ARR_DIMS (arr )[0 ];
584- if (ARR_NDIM (arr ) != 1 ||
585- nelem < 1 ||
586- nelem > INDEX_MAX_KEYS ||
587- ARR_HASNULL (arr ) ||
588- ARR_ELEMTYPE (arr ) != OIDOID )
589- elog (ERROR , "conffeqop is not a 1-D OID array" );
590- memcpy (conffeqop , ARR_DATA_PTR (arr ), nelem * sizeof (Oid ));
591-
592504 /*
593505 * Before creating a new constraint, see whether any existing FKs are
594506 * fit for the purpose. If one is, attach the parent constraint to it,
@@ -1530,6 +1442,115 @@ get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
15301442 return pkattnos ;
15311443}
15321444
1445+ /*
1446+ * Extract data from the pg_constraint tuple of a foreign-key constraint.
1447+ *
1448+ * All arguments save the first are output arguments; the last three of them
1449+ * can be passed as NULL if caller doesn't need them.
1450+ */
1451+ void
1452+ DeconstructFkConstraintRow (HeapTuple tuple , int * numfks ,
1453+ AttrNumber * conkey , AttrNumber * confkey ,
1454+ Oid * pf_eq_oprs , Oid * pp_eq_oprs , Oid * ff_eq_oprs )
1455+ {
1456+ Oid constrId ;
1457+ Datum adatum ;
1458+ bool isNull ;
1459+ ArrayType * arr ;
1460+ int numkeys ;
1461+
1462+ constrId = ((Form_pg_constraint ) GETSTRUCT (tuple ))-> oid ;
1463+
1464+ /*
1465+ * We expect the arrays to be 1-D arrays of the right types; verify that.
1466+ * We don't need to use deconstruct_array() since the array data is just
1467+ * going to look like a C array of values.
1468+ */
1469+ adatum = SysCacheGetAttr (CONSTROID , tuple ,
1470+ Anum_pg_constraint_conkey , & isNull );
1471+ if (isNull )
1472+ elog (ERROR , "null conkey for constraint %u" , constrId );
1473+ arr = DatumGetArrayTypeP (adatum ); /* ensure not toasted */
1474+ if (ARR_NDIM (arr ) != 1 ||
1475+ ARR_HASNULL (arr ) ||
1476+ ARR_ELEMTYPE (arr ) != INT2OID )
1477+ elog (ERROR , "conkey is not a 1-D smallint array" );
1478+ numkeys = ARR_DIMS (arr )[0 ];
1479+ if (numkeys <= 0 || numkeys > INDEX_MAX_KEYS )
1480+ elog (ERROR , "foreign key constraint cannot have %d columns" , numkeys );
1481+ memcpy (conkey , ARR_DATA_PTR (arr ), numkeys * sizeof (int16 ));
1482+ if ((Pointer ) arr != DatumGetPointer (adatum ))
1483+ pfree (arr ); /* free de-toasted copy, if any */
1484+
1485+ adatum = SysCacheGetAttr (CONSTROID , tuple ,
1486+ Anum_pg_constraint_confkey , & isNull );
1487+ if (isNull )
1488+ elog (ERROR , "null confkey for constraint %u" , constrId );
1489+ arr = DatumGetArrayTypeP (adatum ); /* ensure not toasted */
1490+ if (ARR_NDIM (arr ) != 1 ||
1491+ ARR_DIMS (arr )[0 ] != numkeys ||
1492+ ARR_HASNULL (arr ) ||
1493+ ARR_ELEMTYPE (arr ) != INT2OID )
1494+ elog (ERROR , "confkey is not a 1-D smallint array" );
1495+ memcpy (confkey , ARR_DATA_PTR (arr ), numkeys * sizeof (int16 ));
1496+ if ((Pointer ) arr != DatumGetPointer (adatum ))
1497+ pfree (arr ); /* free de-toasted copy, if any */
1498+
1499+ if (pf_eq_oprs )
1500+ {
1501+ adatum = SysCacheGetAttr (CONSTROID , tuple ,
1502+ Anum_pg_constraint_conpfeqop , & isNull );
1503+ if (isNull )
1504+ elog (ERROR , "null conpfeqop for constraint %u" , constrId );
1505+ arr = DatumGetArrayTypeP (adatum ); /* ensure not toasted */
1506+ /* see TryReuseForeignKey if you change the test below */
1507+ if (ARR_NDIM (arr ) != 1 ||
1508+ ARR_DIMS (arr )[0 ] != numkeys ||
1509+ ARR_HASNULL (arr ) ||
1510+ ARR_ELEMTYPE (arr ) != OIDOID )
1511+ elog (ERROR , "conpfeqop is not a 1-D Oid array" );
1512+ memcpy (pf_eq_oprs , ARR_DATA_PTR (arr ), numkeys * sizeof (Oid ));
1513+ if ((Pointer ) arr != DatumGetPointer (adatum ))
1514+ pfree (arr ); /* free de-toasted copy, if any */
1515+ }
1516+
1517+ if (pp_eq_oprs )
1518+ {
1519+ adatum = SysCacheGetAttr (CONSTROID , tuple ,
1520+ Anum_pg_constraint_conppeqop , & isNull );
1521+ if (isNull )
1522+ elog (ERROR , "null conppeqop for constraint %u" , constrId );
1523+ arr = DatumGetArrayTypeP (adatum ); /* ensure not toasted */
1524+ if (ARR_NDIM (arr ) != 1 ||
1525+ ARR_DIMS (arr )[0 ] != numkeys ||
1526+ ARR_HASNULL (arr ) ||
1527+ ARR_ELEMTYPE (arr ) != OIDOID )
1528+ elog (ERROR , "conppeqop is not a 1-D Oid array" );
1529+ memcpy (pp_eq_oprs , ARR_DATA_PTR (arr ), numkeys * sizeof (Oid ));
1530+ if ((Pointer ) arr != DatumGetPointer (adatum ))
1531+ pfree (arr ); /* free de-toasted copy, if any */
1532+ }
1533+
1534+ if (ff_eq_oprs )
1535+ {
1536+ adatum = SysCacheGetAttr (CONSTROID , tuple ,
1537+ Anum_pg_constraint_conffeqop , & isNull );
1538+ if (isNull )
1539+ elog (ERROR , "null conffeqop for constraint %u" , constrId );
1540+ arr = DatumGetArrayTypeP (adatum ); /* ensure not toasted */
1541+ if (ARR_NDIM (arr ) != 1 ||
1542+ ARR_DIMS (arr )[0 ] != numkeys ||
1543+ ARR_HASNULL (arr ) ||
1544+ ARR_ELEMTYPE (arr ) != OIDOID )
1545+ elog (ERROR , "conffeqop is not a 1-D Oid array" );
1546+ memcpy (ff_eq_oprs , ARR_DATA_PTR (arr ), numkeys * sizeof (Oid ));
1547+ if ((Pointer ) arr != DatumGetPointer (adatum ))
1548+ pfree (arr ); /* free de-toasted copy, if any */
1549+ }
1550+
1551+ * numfks = numkeys ;
1552+ }
1553+
15331554/*
15341555 * Determine whether a relation can be proven functionally dependent on
15351556 * a set of grouping columns. If so, return true and add the pg_constraint
0 commit comments