diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index c24396724f4..983f631234b 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -303,60 +303,6 @@ RI_FKey_check(TriggerData *trigdata)
fk_rel = trigdata->tg_relation;
pk_rel = heap_open(riinfo->pk_relid, RowShareLock);
- /* ----------
- * SQL:2008 4.17.3
- * If Rf and Rt are empty (no columns to compare given)
- * constraint is true if 0 < (SELECT COUNT(*) FROM T)
- *
- * Note: The special case that no columns are given cannot
- * occur at present in Postgres (and is disallowed by the
- * standard too); it's just there for future enhancements.
- * ----------
- */
- if (riinfo->nkeys == 0)
- {
- if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect failed");
-
- ri_BuildQueryKey(&qkey, riinfo, RI_PLAN_CHECK_LOOKUPPK);
-
- if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL)
- {
- char querystr[MAX_QUOTED_REL_NAME_LEN + 100];
- char pkrelname[MAX_QUOTED_REL_NAME_LEN];
-
- /* ---------
- * The query string built is
- * SELECT 1 FROM ONLY
- * ----------
- */
- quoteRelationName(pkrelname, pk_rel);
- snprintf(querystr, sizeof(querystr),
- "SELECT 1 FROM ONLY %s x FOR SHARE OF x",
- pkrelname);
-
- /* Prepare and save the plan */
- qplan = ri_PlanCheck(querystr, 0, NULL,
- &qkey, fk_rel, pk_rel, true);
- }
-
- /*
- * Execute the plan
- */
- ri_PerformCheck(riinfo, &qkey, qplan,
- fk_rel, pk_rel,
- NULL, NULL,
- false,
- SPI_OK_SELECT);
-
- if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish failed");
-
- heap_close(pk_rel, RowShareLock);
-
- return PointerGetDatum(NULL);
- }
-
if (riinfo->confmatchtype == FKCONSTR_MATCH_PARTIAL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -704,12 +650,6 @@ ri_restrict_del(TriggerData *trigdata, bool is_no_action)
riinfo = ri_FetchConstraintInfo(trigdata->tg_trigger,
trigdata->tg_relation, true);
- /*
- * Nothing to do if no column names to compare given
- */
- if (riinfo->nkeys == 0)
- return PointerGetDatum(NULL);
-
/*
* Get the relation descriptors of the FK and PK tables and the old tuple.
*
@@ -922,12 +862,6 @@ ri_restrict_upd(TriggerData *trigdata, bool is_no_action)
riinfo = ri_FetchConstraintInfo(trigdata->tg_trigger,
trigdata->tg_relation, true);
- /*
- * Nothing to do if no column names to compare given
- */
- if (riinfo->nkeys == 0)
- return PointerGetDatum(NULL);
-
/*
* Get the relation descriptors of the FK and PK tables and the new and
* old tuple.
@@ -1109,12 +1043,6 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
riinfo = ri_FetchConstraintInfo(trigdata->tg_trigger,
trigdata->tg_relation, true);
- /*
- * Nothing to do if no column names to compare given
- */
- if (riinfo->nkeys == 0)
- return PointerGetDatum(NULL);
-
/*
* Get the relation descriptors of the FK and PK tables and the old tuple.
*
@@ -1273,12 +1201,6 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
riinfo = ri_FetchConstraintInfo(trigdata->tg_trigger,
trigdata->tg_relation, true);
- /*
- * Nothing to do if no column names to compare given
- */
- if (riinfo->nkeys == 0)
- return PointerGetDatum(NULL);
-
/*
* Get the relation descriptors of the FK and PK tables and the new and
* old tuple.
@@ -1458,12 +1380,6 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS)
riinfo = ri_FetchConstraintInfo(trigdata->tg_trigger,
trigdata->tg_relation, true);
- /*
- * Nothing to do if no column names to compare given
- */
- if (riinfo->nkeys == 0)
- return PointerGetDatum(NULL);
-
/*
* Get the relation descriptors of the FK and PK tables and the old tuple.
*
@@ -1630,12 +1546,6 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
riinfo = ri_FetchConstraintInfo(trigdata->tg_trigger,
trigdata->tg_relation, true);
- /*
- * Nothing to do if no column names to compare given
- */
- if (riinfo->nkeys == 0)
- return PointerGetDatum(NULL);
-
/*
* Get the relation descriptors of the FK and PK tables and the old tuple.
*
@@ -1810,12 +1720,6 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
riinfo = ri_FetchConstraintInfo(trigdata->tg_trigger,
trigdata->tg_relation, true);
- /*
- * Nothing to do if no column names to compare given
- */
- if (riinfo->nkeys == 0)
- return PointerGetDatum(NULL);
-
/*
* Get the relation descriptors of the FK and PK tables and the old tuple.
*
@@ -1997,12 +1901,6 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
riinfo = ri_FetchConstraintInfo(trigdata->tg_trigger,
trigdata->tg_relation, true);
- /*
- * Nothing to do if no column names to compare given
- */
- if (riinfo->nkeys == 0)
- return PointerGetDatum(NULL);
-
/*
* Get the relation descriptors of the FK and PK tables and the old tuple.
*
@@ -2186,13 +2084,6 @@ RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel,
*/
riinfo = ri_FetchConstraintInfo(trigger, pk_rel, true);
- /*
- * Nothing to do if no columns (satisfaction of such a constraint only
- * requires existence of a PK row, and this update won't change that).
- */
- if (riinfo->nkeys == 0)
- return false;
-
switch (riinfo->confmatchtype)
{
case FKCONSTR_MATCH_SIMPLE:
@@ -2250,13 +2141,6 @@ RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel,
*/
riinfo = ri_FetchConstraintInfo(trigger, fk_rel, false);
- /*
- * Nothing to do if no columns (satisfaction of such a constraint only
- * requires existence of a PK row, and this update won't change that).
- */
- if (riinfo->nkeys == 0)
- return false;
-
switch (riinfo->confmatchtype)
{
case FKCONSTR_MATCH_SIMPLE:
@@ -2945,13 +2829,13 @@ ri_LoadConstraintInfo(Oid constraintOid)
if (isNull)
elog(ERROR, "null conkey for constraint %u", constraintOid);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
- numkeys = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
- numkeys < 0 ||
- numkeys > RI_MAX_NUMKEYS ||
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))
@@ -2962,10 +2846,8 @@ ri_LoadConstraintInfo(Oid constraintOid)
if (isNull)
elog(ERROR, "null confkey for constraint %u", constraintOid);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
- numkeys = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
- numkeys != riinfo->nkeys ||
- numkeys > RI_MAX_NUMKEYS ||
+ ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != INT2OID)
elog(ERROR, "confkey is not a 1-D smallint array");
@@ -2978,11 +2860,9 @@ ri_LoadConstraintInfo(Oid constraintOid)
if (isNull)
elog(ERROR, "null conpfeqop for constraint %u", constraintOid);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
- numkeys = ARR_DIMS(arr)[0];
/* see TryReuseForeignKey if you change the test below */
if (ARR_NDIM(arr) != 1 ||
- numkeys != riinfo->nkeys ||
- numkeys > RI_MAX_NUMKEYS ||
+ ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conpfeqop is not a 1-D Oid array");
@@ -2995,10 +2875,8 @@ ri_LoadConstraintInfo(Oid constraintOid)
if (isNull)
elog(ERROR, "null conppeqop for constraint %u", constraintOid);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
- numkeys = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
- numkeys != riinfo->nkeys ||
- numkeys > RI_MAX_NUMKEYS ||
+ ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conppeqop is not a 1-D Oid array");
@@ -3011,10 +2889,8 @@ ri_LoadConstraintInfo(Oid constraintOid)
if (isNull)
elog(ERROR, "null conffeqop for constraint %u", constraintOid);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
- numkeys = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
- numkeys != riinfo->nkeys ||
- numkeys > RI_MAX_NUMKEYS ||
+ ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conffeqop is not a 1-D Oid array");
@@ -3311,22 +3187,6 @@ ri_ReportViolation(const RI_ConstraintInfo *riinfo,
tupdesc = pk_rel->rd_att;
}
- /*
- * Special case - if there are no keys at all, this is a 'no column'
- * constraint - no need to try to extract the values, and the message in
- * this case looks different.
- */
- if (riinfo->nkeys == 0)
- {
- ereport(ERROR,
- (errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
- errmsg("insert or update on table \"%s\" violates foreign key constraint \"%s\"",
- RelationGetRelationName(fk_rel),
- NameStr(riinfo->conname)),
- errdetail("No rows were found in \"%s\".",
- RelationGetRelationName(pk_rel))));
- }
-
/* Get printable versions of the keys involved */
initStringInfo(&key_names);
initStringInfo(&key_values);