fk_rel = trigdata->tg_relation;
pk_rel = heap_open(riinfo->pk_relid, RowShareLock);
- /* ----------
- * SQL:2008 4.17.3 <Table constraints>
- * 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 <pktable>
- * ----------
- */
- 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),
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.
*
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.
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.
*
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.
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.
*
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.
*
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.
*
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.
*
*/
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:
*/
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:
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))
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");
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");
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");
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");
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);