aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2019-01-18 14:40:13 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2019-01-18 14:59:44 -0300
commit0080396dad4fe59a91f6d7e9c1f806affcfc68c3 (patch)
treeba3f39628888a2abc16f848f10e4f41d35bcf503 /src
parent9194c4270b28bb19b43a0156e5a296d1a0a3dd48 (diff)
downloadpostgresql-0080396dad4fe59a91f6d7e9c1f806affcfc68c3.tar.gz
postgresql-0080396dad4fe59a91f6d7e9c1f806affcfc68c3.zip
Refactor duplicate code into DeconstructFkConstraintRow
My commit 3de241dba86f 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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/pg_constraint.c201
-rw-r--r--src/backend/utils/adt/ri_triggers.c89
-rw-r--r--src/backend/utils/cache/relcache.c61
-rw-r--r--src/include/catalog/pg_constraint.h3
4 files changed, 126 insertions, 228 deletions
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 3c960c9423a..cfd131460d1 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -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,
@@ -1531,6 +1443,115 @@ get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
}
/*
+ * 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
* OIDs of the constraints needed for the proof to the *constraintDeps list.
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index e606eb342fd..0c1ee8d1f69 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -2189,10 +2189,6 @@ ri_LoadConstraintInfo(Oid constraintOid)
bool found;
HeapTuple tup;
Form_pg_constraint conForm;
- Datum adatum;
- bool isNull;
- ArrayType *arr;
- int numkeys;
/*
* On the first call initialize the hashtable
@@ -2234,84 +2230,13 @@ ri_LoadConstraintInfo(Oid constraintOid)
riinfo->confdeltype = conForm->confdeltype;
riinfo->confmatchtype = conForm->confmatchtype;
- /*
- * 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, tup,
- Anum_pg_constraint_conkey, &isNull);
- if (isNull)
- elog(ERROR, "null conkey for constraint %u", constraintOid);
- 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 > RI_MAX_NUMKEYS)
- elog(ERROR, "foreign key constraint cannot have %d columns", numkeys);
- riinfo->nkeys = numkeys;
- memcpy(riinfo->fk_attnums, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
- if ((Pointer) arr != DatumGetPointer(adatum))
- pfree(arr); /* free de-toasted copy, if any */
-
- adatum = SysCacheGetAttr(CONSTROID, tup,
- Anum_pg_constraint_confkey, &isNull);
- if (isNull)
- elog(ERROR, "null confkey for constraint %u", constraintOid);
- 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(riinfo->pk_attnums, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
- if ((Pointer) arr != DatumGetPointer(adatum))
- pfree(arr); /* free de-toasted copy, if any */
-
- adatum = SysCacheGetAttr(CONSTROID, tup,
- Anum_pg_constraint_conpfeqop, &isNull);
- if (isNull)
- elog(ERROR, "null conpfeqop for constraint %u", constraintOid);
- 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(riinfo->pf_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
- if ((Pointer) arr != DatumGetPointer(adatum))
- pfree(arr); /* free de-toasted copy, if any */
-
- adatum = SysCacheGetAttr(CONSTROID, tup,
- Anum_pg_constraint_conppeqop, &isNull);
- if (isNull)
- elog(ERROR, "null conppeqop for constraint %u", constraintOid);
- 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(riinfo->pp_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
- if ((Pointer) arr != DatumGetPointer(adatum))
- pfree(arr); /* free de-toasted copy, if any */
-
- adatum = SysCacheGetAttr(CONSTROID, tup,
- Anum_pg_constraint_conffeqop, &isNull);
- if (isNull)
- elog(ERROR, "null conffeqop for constraint %u", constraintOid);
- 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(riinfo->ff_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
- if ((Pointer) arr != DatumGetPointer(adatum))
- pfree(arr); /* free de-toasted copy, if any */
+ DeconstructFkConstraintRow(tup,
+ &riinfo->nkeys,
+ riinfo->fk_attnums,
+ riinfo->pk_attnums,
+ riinfo->pf_eq_oprs,
+ riinfo->pp_eq_oprs,
+ riinfo->ff_eq_oprs);
ReleaseSysCache(tup);
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index e3b1473e6c9..7ea371a3c71 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -4125,10 +4125,6 @@ RelationGetFKeyList(Relation relation)
{
Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
ForeignKeyCacheInfo *info;
- Datum adatum;
- bool isnull;
- ArrayType *arr;
- int nelem;
/* consider only foreign keys */
if (constraint->contype != CONSTRAINT_FOREIGN)
@@ -4139,58 +4135,11 @@ RelationGetFKeyList(Relation relation)
info->conrelid = constraint->conrelid;
info->confrelid = constraint->confrelid;
- /* Extract data from conkey field */
- adatum = fastgetattr(htup, Anum_pg_constraint_conkey,
- conrel->rd_att, &isnull);
- if (isnull)
- elog(ERROR, "null conkey for rel %s",
- RelationGetRelationName(relation));
-
- arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
- 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");
-
- info->nkeys = nelem;
- memcpy(info->conkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
-
- /* Likewise for confkey */
- adatum = fastgetattr(htup, Anum_pg_constraint_confkey,
- conrel->rd_att, &isnull);
- if (isnull)
- elog(ERROR, "null confkey for rel %s",
- RelationGetRelationName(relation));
-
- arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
- nelem = ARR_DIMS(arr)[0];
- if (ARR_NDIM(arr) != 1 ||
- nelem != info->nkeys ||
- ARR_HASNULL(arr) ||
- ARR_ELEMTYPE(arr) != INT2OID)
- elog(ERROR, "confkey is not a 1-D smallint array");
-
- memcpy(info->confkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
-
- /* Likewise for conpfeqop */
- adatum = fastgetattr(htup, Anum_pg_constraint_conpfeqop,
- conrel->rd_att, &isnull);
- if (isnull)
- elog(ERROR, "null conpfeqop for rel %s",
- RelationGetRelationName(relation));
-
- arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
- nelem = ARR_DIMS(arr)[0];
- if (ARR_NDIM(arr) != 1 ||
- nelem != info->nkeys ||
- ARR_HASNULL(arr) ||
- ARR_ELEMTYPE(arr) != OIDOID)
- elog(ERROR, "conpfeqop is not a 1-D OID array");
-
- memcpy(info->conpfeqop, ARR_DATA_PTR(arr), nelem * sizeof(Oid));
+ DeconstructFkConstraintRow(htup, &info->nkeys,
+ info->conkey,
+ info->confkey,
+ info->conpfeqop,
+ NULL, NULL);
/* Add FK's node to the result list */
result = lappend(result, info);
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index d2eafd10df4..0944dc8be74 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -251,6 +251,9 @@ extern Oid get_relation_idx_constraint_oid(Oid relationId, Oid indexId);
extern Bitmapset *get_primary_key_attnos(Oid relid, bool deferrableOk,
Oid *constraintOid);
+extern void DeconstructFkConstraintRow(HeapTuple tuple, int *numfks,
+ AttrNumber *conkey, AttrNumber *confkey,
+ Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs);
extern bool check_functional_grouping(Oid relid,
Index varno, Index varlevelsup,