@@ -450,14 +450,11 @@ static void
450
450
clone_fk_constraints (Relation pg_constraint , Relation parentRel ,
451
451
Relation partRel , List * clone , List * * cloned )
452
452
{
453
- TupleDesc tupdesc ;
454
453
AttrNumber * attmap ;
455
454
List * partFKs ;
456
455
List * subclone = NIL ;
457
456
ListCell * cell ;
458
457
459
- tupdesc = RelationGetDescr (pg_constraint );
460
-
461
458
/*
462
459
* The constraint key may differ, if the columns in the partition are
463
460
* different. This map is used to convert them.
@@ -487,9 +484,6 @@ clone_fk_constraints(Relation pg_constraint, Relation parentRel,
487
484
int nelem ;
488
485
ListCell * cell ;
489
486
int i ;
490
- ArrayType * arr ;
491
- Datum datum ;
492
- bool isnull ;
493
487
494
488
tuple = SearchSysCache1 (CONSTROID , parentConstrOid );
495
489
if (!tuple )
@@ -506,93 +500,11 @@ clone_fk_constraints(Relation pg_constraint, Relation parentRel,
506
500
507
501
ObjectAddressSet (parentAddr , ConstraintRelationId , parentConstrOid );
508
502
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 );
523
505
for (i = 0 ; i < nelem ; i ++ )
524
506
mapped_conkey [i ] = attmap [conkey [i ] - 1 ];
525
507
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
-
596
508
/*
597
509
* Before creating a new constraint, see whether any existing FKs are
598
510
* 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)
1536
1448
return pkattnos ;
1537
1449
}
1538
1450
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
+
1539
1558
/*
1540
1559
* Determine whether a relation can be proven functionally dependent on
1541
1560
* a set of grouping columns. If so, return true and add the pg_constraint
0 commit comments