@@ -446,14 +446,11 @@ static void
446
446
clone_fk_constraints (Relation pg_constraint , Relation parentRel ,
447
447
Relation partRel , List * clone , List * * cloned )
448
448
{
449
- TupleDesc tupdesc ;
450
449
AttrNumber * attmap ;
451
450
List * partFKs ;
452
451
List * subclone = NIL ;
453
452
ListCell * cell ;
454
453
455
- tupdesc = RelationGetDescr (pg_constraint );
456
-
457
454
/*
458
455
* The constraint key may differ, if the columns in the partition are
459
456
* different. This map is used to convert them.
@@ -483,9 +480,6 @@ clone_fk_constraints(Relation pg_constraint, Relation parentRel,
483
480
int nelem ;
484
481
ListCell * cell ;
485
482
int i ;
486
- ArrayType * arr ;
487
- Datum datum ;
488
- bool isnull ;
489
483
490
484
tuple = SearchSysCache1 (CONSTROID , parentConstrOid );
491
485
if (!tuple )
@@ -502,93 +496,11 @@ clone_fk_constraints(Relation pg_constraint, Relation parentRel,
502
496
503
497
ObjectAddressSet (parentAddr , ConstraintRelationId , parentConstrOid );
504
498
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 );
519
501
for (i = 0 ; i < nelem ; i ++ )
520
502
mapped_conkey [i ] = attmap [conkey [i ] - 1 ];
521
503
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
-
592
504
/*
593
505
* Before creating a new constraint, see whether any existing FKs are
594
506
* 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)
1530
1442
return pkattnos ;
1531
1443
}
1532
1444
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
+
1533
1554
/*
1534
1555
* Determine whether a relation can be proven functionally dependent on
1535
1556
* a set of grouping columns. If so, return true and add the pg_constraint
0 commit comments