1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-24 00:23:06 +03:00

Refactor duplicate code into DeconstructFkConstraintRow

My commit 3de241dba8 introduced some code (in tablecmds.c) to obtain
data from a pg_constraint row for a foreign key, that already existed in
ri_triggers.c.  Split it out into its own routine in pg_constraint.c,
where it naturally belongs.

No functional code changes, only code movement.

Backpatch to pg11, because a future bugfix is simpler after this.
This commit is contained in:
Alvaro Herrera
2019-01-18 14:40:13 -03:00
parent 9194c4270b
commit 0080396dad
4 changed files with 126 additions and 228 deletions

View File

@@ -446,14 +446,11 @@ static void
clone_fk_constraints(Relation pg_constraint, Relation parentRel,
Relation partRel, List *clone, List **cloned)
{
TupleDesc tupdesc;
AttrNumber *attmap;
List *partFKs;
List *subclone = NIL;
ListCell *cell;
tupdesc = RelationGetDescr(pg_constraint);
/*
* The constraint key may differ, if the columns in the partition are
* different. This map is used to convert them.
@@ -483,9 +480,6 @@ clone_fk_constraints(Relation pg_constraint, Relation parentRel,
int nelem;
ListCell *cell;
int i;
ArrayType *arr;
Datum datum;
bool isnull;
tuple = SearchSysCache1(CONSTROID, parentConstrOid);
if (!tuple)
@@ -502,93 +496,11 @@ clone_fk_constraints(Relation pg_constraint, Relation parentRel,
ObjectAddressSet(parentAddr, ConstraintRelationId, parentConstrOid);
datum = fastgetattr(tuple, Anum_pg_constraint_conkey,
tupdesc, &isnull);
if (isnull)
elog(ERROR, "null conkey");
arr = DatumGetArrayTypeP(datum);
nelem = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
nelem < 1 ||
nelem > INDEX_MAX_KEYS ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != INT2OID)
elog(ERROR, "conkey is not a 1-D smallint array");
memcpy(conkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
DeconstructFkConstraintRow(tuple, &nelem, conkey, confkey,
conpfeqop, conppeqop, conffeqop);
for (i = 0; i < nelem; i++)
mapped_conkey[i] = attmap[conkey[i] - 1];
datum = fastgetattr(tuple, Anum_pg_constraint_confkey,
tupdesc, &isnull);
if (isnull)
elog(ERROR, "null confkey");
arr = DatumGetArrayTypeP(datum);
nelem = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
nelem < 1 ||
nelem > INDEX_MAX_KEYS ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != INT2OID)
elog(ERROR, "confkey is not a 1-D smallint array");
memcpy(confkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
datum = fastgetattr(tuple, Anum_pg_constraint_conpfeqop,
tupdesc, &isnull);
if (isnull)
elog(ERROR, "null conpfeqop");
arr = DatumGetArrayTypeP(datum);
nelem = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
nelem < 1 ||
nelem > INDEX_MAX_KEYS ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conpfeqop is not a 1-D OID array");
memcpy(conpfeqop, ARR_DATA_PTR(arr), nelem * sizeof(Oid));
datum = fastgetattr(tuple, Anum_pg_constraint_conpfeqop,
tupdesc, &isnull);
if (isnull)
elog(ERROR, "null conpfeqop");
arr = DatumGetArrayTypeP(datum);
nelem = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
nelem < 1 ||
nelem > INDEX_MAX_KEYS ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conpfeqop is not a 1-D OID array");
memcpy(conpfeqop, ARR_DATA_PTR(arr), nelem * sizeof(Oid));
datum = fastgetattr(tuple, Anum_pg_constraint_conppeqop,
tupdesc, &isnull);
if (isnull)
elog(ERROR, "null conppeqop");
arr = DatumGetArrayTypeP(datum);
nelem = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
nelem < 1 ||
nelem > INDEX_MAX_KEYS ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conppeqop is not a 1-D OID array");
memcpy(conppeqop, ARR_DATA_PTR(arr), nelem * sizeof(Oid));
datum = fastgetattr(tuple, Anum_pg_constraint_conffeqop,
tupdesc, &isnull);
if (isnull)
elog(ERROR, "null conffeqop");
arr = DatumGetArrayTypeP(datum);
nelem = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
nelem < 1 ||
nelem > INDEX_MAX_KEYS ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conffeqop is not a 1-D OID array");
memcpy(conffeqop, ARR_DATA_PTR(arr), nelem * sizeof(Oid));
/*
* Before creating a new constraint, see whether any existing FKs are
* 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)
return pkattnos;
}
/*
* Extract data from the pg_constraint tuple of a foreign-key constraint.
*
* All arguments save the first are output arguments; the last three of them
* can be passed as NULL if caller doesn't need them.
*/
void
DeconstructFkConstraintRow(HeapTuple tuple, int *numfks,
AttrNumber *conkey, AttrNumber *confkey,
Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs)
{
Oid constrId;
Datum adatum;
bool isNull;
ArrayType *arr;
int numkeys;
constrId = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
/*
* We expect the arrays to be 1-D arrays of the right types; verify that.
* We don't need to use deconstruct_array() since the array data is just
* going to look like a C array of values.
*/
adatum = SysCacheGetAttr(CONSTROID, tuple,
Anum_pg_constraint_conkey, &isNull);
if (isNull)
elog(ERROR, "null conkey for constraint %u", constrId);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
if (ARR_NDIM(arr) != 1 ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != INT2OID)
elog(ERROR, "conkey is not a 1-D smallint array");
numkeys = ARR_DIMS(arr)[0];
if (numkeys <= 0 || numkeys > INDEX_MAX_KEYS)
elog(ERROR, "foreign key constraint cannot have %d columns", numkeys);
memcpy(conkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
if ((Pointer) arr != DatumGetPointer(adatum))
pfree(arr); /* free de-toasted copy, if any */
adatum = SysCacheGetAttr(CONSTROID, tuple,
Anum_pg_constraint_confkey, &isNull);
if (isNull)
elog(ERROR, "null confkey for constraint %u", constrId);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
if (ARR_NDIM(arr) != 1 ||
ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != INT2OID)
elog(ERROR, "confkey is not a 1-D smallint array");
memcpy(confkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
if ((Pointer) arr != DatumGetPointer(adatum))
pfree(arr); /* free de-toasted copy, if any */
if (pf_eq_oprs)
{
adatum = SysCacheGetAttr(CONSTROID, tuple,
Anum_pg_constraint_conpfeqop, &isNull);
if (isNull)
elog(ERROR, "null conpfeqop for constraint %u", constrId);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
/* see TryReuseForeignKey if you change the test below */
if (ARR_NDIM(arr) != 1 ||
ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conpfeqop is not a 1-D Oid array");
memcpy(pf_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
if ((Pointer) arr != DatumGetPointer(adatum))
pfree(arr); /* free de-toasted copy, if any */
}
if (pp_eq_oprs)
{
adatum = SysCacheGetAttr(CONSTROID, tuple,
Anum_pg_constraint_conppeqop, &isNull);
if (isNull)
elog(ERROR, "null conppeqop for constraint %u", constrId);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
if (ARR_NDIM(arr) != 1 ||
ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conppeqop is not a 1-D Oid array");
memcpy(pp_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
if ((Pointer) arr != DatumGetPointer(adatum))
pfree(arr); /* free de-toasted copy, if any */
}
if (ff_eq_oprs)
{
adatum = SysCacheGetAttr(CONSTROID, tuple,
Anum_pg_constraint_conffeqop, &isNull);
if (isNull)
elog(ERROR, "null conffeqop for constraint %u", constrId);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
if (ARR_NDIM(arr) != 1 ||
ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conffeqop is not a 1-D Oid array");
memcpy(ff_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
if ((Pointer) arr != DatumGetPointer(adatum))
pfree(arr); /* free de-toasted copy, if any */
}
*numfks = numkeys;
}
/*
* Determine whether a relation can be proven functionally dependent on
* a set of grouping columns. If so, return true and add the pg_constraint