aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/utils/adt/ri_triggers.c496
-rw-r--r--src/include/utils/elog.h4
-rw-r--r--src/test/regress/expected/alter_table.out3
-rw-r--r--src/test/regress/expected/cluster.out3
-rw-r--r--src/test/regress/expected/foreign_key.out93
5 files changed, 280 insertions, 319 deletions
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index b940315bbf1..ed95d8ed6c4 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -17,7 +17,7 @@
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.51 2003/06/11 15:02:25 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.52 2003/07/22 22:14:57 tgl Exp $
*
* ----------
*/
@@ -204,16 +204,8 @@ RI_FKey_check(PG_FUNCTION_ARGS)
*/
ri_CheckTrigger(fcinfo, "RI_FKey_check", RI_TRIGTYPE_INUP);
- /*
- * Check for the correct # of call arguments
- */
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_check()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_check()",
- RI_MAX_NUMKEYS);
/*
* Get the relation descriptors of the FK and PK tables and the new
@@ -221,16 +213,7 @@ RI_FKey_check(PG_FUNCTION_ARGS)
*
* pk_rel is opened in RowShareLock mode since that's what our eventual
* SELECT FOR UPDATE will get on it.
- *
- * Error check here is needed because of ancient pg_dump bug; see notes
- * in CreateTrigger().
*/
- if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
-
pk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowShareLock);
fk_rel = trigdata->tg_relation;
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
@@ -277,7 +260,7 @@ RI_FKey_check(PG_FUNCTION_ARGS)
tgnargs, tgargs);
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_check()");
+ elog(ERROR, "SPI_connect failed");
if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL)
{
@@ -308,7 +291,7 @@ RI_FKey_check(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_check()");
+ elog(ERROR, "SPI_finish failed");
heap_close(pk_rel, RowShareLock);
@@ -319,10 +302,9 @@ RI_FKey_check(PG_FUNCTION_ARGS)
match_type = ri_DetermineMatchType(tgargs[RI_MATCH_TYPE_ARGNO]);
if (match_type == RI_MATCH_TYPE_PARTIAL)
- {
- elog(ERROR, "MATCH PARTIAL not yet supported");
- return PointerGetDatum(NULL);
- }
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
ri_BuildQueryKeyFull(&qkey, trigdata->tg_trigger->tgoid,
RI_PLAN_CHECK_LOOKUPPK, fk_rel, pk_rel,
@@ -356,10 +338,12 @@ RI_FKey_check(PG_FUNCTION_ARGS)
* Not allowed - MATCH FULL says either all or none of
* the attributes can be NULLs
*/
- elog(ERROR, "%s referential integrity violation - "
- "MATCH FULL doesn't allow mixing of NULL "
- "and NON-NULL key values",
- tgargs[RI_CONSTRAINT_NAME_ARGNO]);
+ ereport(ERROR,
+ (errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
+ errmsg("insert or update on \"%s\" violates foreign key constraint \"%s\"",
+ RelationGetRelationName(trigdata->tg_relation),
+ tgargs[RI_CONSTRAINT_NAME_ARGNO]),
+ errdetail("MATCH FULL does not allow mixing of NULL and non-NULL key values.")));
heap_close(pk_rel, RowShareLock);
return PointerGetDatum(NULL);
@@ -380,7 +364,9 @@ RI_FKey_check(PG_FUNCTION_ARGS)
* query below to only include non-null columns, or by
* writing a special version here)
*/
- elog(ERROR, "MATCH PARTIAL not yet implemented");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
heap_close(pk_rel, RowShareLock);
return PointerGetDatum(NULL);
}
@@ -409,7 +395,7 @@ RI_FKey_check(PG_FUNCTION_ARGS)
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_check()");
+ elog(ERROR, "SPI_connect failed");
/*
* Fetch or prepare a saved plan for the real check
@@ -462,7 +448,7 @@ RI_FKey_check(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_check()");
+ elog(ERROR, "SPI_finish failed");
heap_close(pk_rel, RowShareLock);
@@ -554,7 +540,9 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel,
* query below to only include non-null columns, or by
* writing a special version here)
*/
- elog(ERROR, "MATCH PARTIAL not yet implemented");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
break;
}
@@ -568,7 +556,7 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel,
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_check()");
+ elog(ERROR, "SPI_connect failed");
/*
* Fetch or prepare a saved plan for the real check
@@ -620,7 +608,7 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel,
SPI_OK_SELECT, NULL);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in ri_Check_Pk_Match()");
+ elog(ERROR, "SPI_finish failed");
return result;
}
@@ -656,16 +644,8 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS)
*/
ri_CheckTrigger(fcinfo, "RI_FKey_noaction_del", RI_TRIGTYPE_DELETE);
- /*
- * Check for the correct # of call arguments
- */
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_noaction_del()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_noaction_del()",
- RI_MAX_NUMKEYS);
/*
* Nothing to do if no column names to compare given
@@ -680,12 +660,6 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS)
* fk_rel is opened in RowShareLock mode since that's what our eventual
* SELECT FOR UPDATE will get on it.
*/
- if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
-
fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowShareLock);
pk_rel = trigdata->tg_relation;
old_row = trigdata->tg_trigtuple;
@@ -740,7 +714,7 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS)
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_noaction_del()");
+ elog(ERROR, "SPI_connect failed");
/*
* Fetch or prepare a saved plan for the restrict delete
@@ -794,7 +768,7 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_noaction_del()");
+ elog(ERROR, "SPI_finish failed");
heap_close(fk_rel, RowShareLock);
@@ -804,14 +778,16 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS)
* Handle MATCH PARTIAL restrict delete.
*/
case RI_MATCH_TYPE_PARTIAL:
- elog(ERROR, "MATCH PARTIAL not yet supported");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
return PointerGetDatum(NULL);
}
/*
* Never reached
*/
- elog(ERROR, "internal error #2 in ri_triggers.c");
+ elog(ERROR, "invalid match_type");
return PointerGetDatum(NULL);
}
@@ -847,16 +823,8 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
*/
ri_CheckTrigger(fcinfo, "RI_FKey_noaction_upd", RI_TRIGTYPE_UPDATE);
- /*
- * Check for the correct # of call arguments
- */
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_noaction_upd()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_noaction_upd()",
- RI_MAX_NUMKEYS);
/*
* Nothing to do if no column names to compare given
@@ -871,12 +839,6 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
* fk_rel is opened in RowShareLock mode since that's what our eventual
* SELECT FOR UPDATE will get on it.
*/
- if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
-
fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowShareLock);
pk_rel = trigdata->tg_relation;
new_row = trigdata->tg_newtuple;
@@ -943,7 +905,7 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_noaction_upd()");
+ elog(ERROR, "SPI_connect failed");
/*
* Fetch or prepare a saved plan for the noaction update
@@ -997,7 +959,7 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_noaction_upd()");
+ elog(ERROR, "SPI_finish failed");
heap_close(fk_rel, RowShareLock);
@@ -1007,14 +969,16 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
* Handle MATCH PARTIAL noaction update.
*/
case RI_MATCH_TYPE_PARTIAL:
- elog(ERROR, "MATCH PARTIAL not yet supported");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
return PointerGetDatum(NULL);
}
/*
* Never reached
*/
- elog(ERROR, "internal error #3 in ri_triggers.c");
+ elog(ERROR, "invalid match_type");
return PointerGetDatum(NULL);
}
@@ -1046,16 +1010,8 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
*/
ri_CheckTrigger(fcinfo, "RI_FKey_cascade_del", RI_TRIGTYPE_DELETE);
- /*
- * Check for the correct # of call arguments
- */
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_cascade_del()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_cascade_del()",
- RI_MAX_NUMKEYS);
/*
* Nothing to do if no column names to compare given
@@ -1070,12 +1026,6 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
* fk_rel is opened in RowExclusiveLock mode since that's what our
* eventual DELETE will get on it.
*/
- if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
-
fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock);
pk_rel = trigdata->tg_relation;
old_row = trigdata->tg_trigtuple;
@@ -1117,7 +1067,7 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_cascade_del()");
+ elog(ERROR, "SPI_connect failed");
/*
* Fetch or prepare a saved plan for the cascaded delete
@@ -1171,7 +1121,7 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_cascade_del()");
+ elog(ERROR, "SPI_finish failed");
heap_close(fk_rel, RowExclusiveLock);
@@ -1181,14 +1131,16 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
* Handle MATCH PARTIAL cascaded delete.
*/
case RI_MATCH_TYPE_PARTIAL:
- elog(ERROR, "MATCH PARTIAL not yet supported");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
return PointerGetDatum(NULL);
}
/*
* Never reached
*/
- elog(ERROR, "internal error #4 in ri_triggers.c");
+ elog(ERROR, "invalid match_type");
return PointerGetDatum(NULL);
}
@@ -1222,16 +1174,8 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
*/
ri_CheckTrigger(fcinfo, "RI_FKey_cascade_upd", RI_TRIGTYPE_UPDATE);
- /*
- * Check for the correct # of call arguments
- */
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_cascade_upd()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_cascade_upd()",
- RI_MAX_NUMKEYS);
/*
* Nothing to do if no column names to compare given
@@ -1246,12 +1190,6 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
* fk_rel is opened in RowExclusiveLock mode since that's what our
* eventual UPDATE will get on it.
*/
- if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
-
fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock);
pk_rel = trigdata->tg_relation;
new_row = trigdata->tg_newtuple;
@@ -1304,7 +1242,7 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_cascade_upd()");
+ elog(ERROR, "SPI_connect failed");
/*
* Fetch or prepare a saved plan for the cascaded update of
@@ -1367,7 +1305,7 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_cascade_upd()");
+ elog(ERROR, "SPI_finish failed");
heap_close(fk_rel, RowExclusiveLock);
@@ -1377,14 +1315,16 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
* Handle MATCH PARTIAL cascade update.
*/
case RI_MATCH_TYPE_PARTIAL:
- elog(ERROR, "MATCH PARTIAL not yet supported");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
return PointerGetDatum(NULL);
}
/*
* Never reached
*/
- elog(ERROR, "internal error #5 in ri_triggers.c");
+ elog(ERROR, "invalid match_type");
return PointerGetDatum(NULL);
}
@@ -1423,16 +1363,8 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS)
*/
ri_CheckTrigger(fcinfo, "RI_FKey_restrict_del", RI_TRIGTYPE_DELETE);
- /*
- * Check for the correct # of call arguments
- */
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_restrict_del()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_restrict_del()",
- RI_MAX_NUMKEYS);
/*
* Nothing to do if no column names to compare given
@@ -1447,12 +1379,6 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS)
* fk_rel is opened in RowShareLock mode since that's what our eventual
* SELECT FOR UPDATE will get on it.
*/
- if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
-
fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowShareLock);
pk_rel = trigdata->tg_relation;
old_row = trigdata->tg_trigtuple;
@@ -1494,7 +1420,7 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS)
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_restrict_del()");
+ elog(ERROR, "SPI_connect failed");
/*
* Fetch or prepare a saved plan for the restrict delete
@@ -1548,7 +1474,7 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_restrict_del()");
+ elog(ERROR, "SPI_finish failed");
heap_close(fk_rel, RowShareLock);
@@ -1558,14 +1484,16 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS)
* Handle MATCH PARTIAL restrict delete.
*/
case RI_MATCH_TYPE_PARTIAL:
- elog(ERROR, "MATCH PARTIAL not yet supported");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
return PointerGetDatum(NULL);
}
/*
* Never reached
*/
- elog(ERROR, "internal error #6 in ri_triggers.c");
+ elog(ERROR, "invalid match_type");
return PointerGetDatum(NULL);
}
@@ -1605,16 +1533,8 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
*/
ri_CheckTrigger(fcinfo, "RI_FKey_restrict_upd", RI_TRIGTYPE_UPDATE);
- /*
- * Check for the correct # of call arguments
- */
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_restrict_upd()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_restrict_upd()",
- RI_MAX_NUMKEYS);
/*
* Nothing to do if no column names to compare given
@@ -1629,12 +1549,6 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
* fk_rel is opened in RowShareLock mode since that's what our eventual
* SELECT FOR UPDATE will get on it.
*/
- if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
-
fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowShareLock);
pk_rel = trigdata->tg_relation;
new_row = trigdata->tg_newtuple;
@@ -1687,7 +1601,7 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_restrict_upd()");
+ elog(ERROR, "SPI_connect failed");
/*
* Fetch or prepare a saved plan for the restrict update
@@ -1741,7 +1655,7 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_restrict_upd()");
+ elog(ERROR, "SPI_finish failed");
heap_close(fk_rel, RowShareLock);
@@ -1751,14 +1665,16 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
* Handle MATCH PARTIAL restrict update.
*/
case RI_MATCH_TYPE_PARTIAL:
- elog(ERROR, "MATCH PARTIAL not yet supported");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
return PointerGetDatum(NULL);
}
/*
* Never reached
*/
- elog(ERROR, "internal error #7 in ri_triggers.c");
+ elog(ERROR, "invalid match_type");
return PointerGetDatum(NULL);
}
@@ -1790,16 +1706,8 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS)
*/
ri_CheckTrigger(fcinfo, "RI_FKey_setnull_del", RI_TRIGTYPE_DELETE);
- /*
- * Check for the correct # of call arguments
- */
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_setnull_del()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_setnull_del()",
- RI_MAX_NUMKEYS);
/*
* Nothing to do if no column names to compare given
@@ -1814,12 +1722,6 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS)
* fk_rel is opened in RowExclusiveLock mode since that's what our
* eventual UPDATE will get on it.
*/
- if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
-
fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock);
pk_rel = trigdata->tg_relation;
old_row = trigdata->tg_trigtuple;
@@ -1861,7 +1763,7 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS)
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_setnull_del()");
+ elog(ERROR, "SPI_connect failed");
/*
* Fetch or prepare a saved plan for the set null delete
@@ -1923,7 +1825,7 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_setnull_del()");
+ elog(ERROR, "SPI_finish failed");
heap_close(fk_rel, RowExclusiveLock);
@@ -1933,14 +1835,16 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS)
* Handle MATCH PARTIAL set null delete.
*/
case RI_MATCH_TYPE_PARTIAL:
- elog(ERROR, "MATCH PARTIAL not yet supported");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
return PointerGetDatum(NULL);
}
/*
* Never reached
*/
- elog(ERROR, "internal error #8 in ri_triggers.c");
+ elog(ERROR, "invalid match_type");
return PointerGetDatum(NULL);
}
@@ -1975,16 +1879,8 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
*/
ri_CheckTrigger(fcinfo, "RI_FKey_setnull_upd", RI_TRIGTYPE_UPDATE);
- /*
- * Check for the correct # of call arguments
- */
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_setnull_upd()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_setnull_upd()",
- RI_MAX_NUMKEYS);
/*
* Nothing to do if no column names to compare given
@@ -1999,12 +1895,6 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
* fk_rel is opened in RowExclusiveLock mode since that's what our
* eventual UPDATE will get on it.
*/
- if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
-
fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock);
pk_rel = trigdata->tg_relation;
new_row = trigdata->tg_newtuple;
@@ -2058,7 +1948,7 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_setnull_upd()");
+ elog(ERROR, "SPI_connect failed");
/*
* "MATCH <unspecified>" only changes columns corresponding to
@@ -2153,7 +2043,7 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_setnull_upd()");
+ elog(ERROR, "SPI_finish failed");
heap_close(fk_rel, RowExclusiveLock);
@@ -2163,14 +2053,16 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
* Handle MATCH PARTIAL set null update.
*/
case RI_MATCH_TYPE_PARTIAL:
- elog(ERROR, "MATCH PARTIAL not yet supported");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
return PointerGetDatum(NULL);
}
/*
* Never reached
*/
- elog(ERROR, "internal error #9 in ri_triggers.c");
+ elog(ERROR, "invalid match_type");
return PointerGetDatum(NULL);
}
@@ -2201,16 +2093,8 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
*/
ri_CheckTrigger(fcinfo, "RI_FKey_setdefault_del", RI_TRIGTYPE_DELETE);
- /*
- * Check for the correct # of call arguments
- */
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_setdefault_del()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_setdefault_del()",
- RI_MAX_NUMKEYS);
/*
* Nothing to do if no column names to compare given
@@ -2225,12 +2109,6 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
* fk_rel is opened in RowExclusiveLock mode since that's what our
* eventual UPDATE will get on it.
*/
- if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
-
fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock);
pk_rel = trigdata->tg_relation;
old_row = trigdata->tg_trigtuple;
@@ -2272,7 +2150,7 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_setdefault_del()");
+ elog(ERROR, "SPI_connect failed");
/*
* Prepare a plan for the set default delete operation.
@@ -2365,7 +2243,7 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_setdefault_del()");
+ elog(ERROR, "SPI_finish failed");
heap_close(fk_rel, RowExclusiveLock);
@@ -2385,14 +2263,16 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
* Handle MATCH PARTIAL set null delete.
*/
case RI_MATCH_TYPE_PARTIAL:
- elog(ERROR, "MATCH PARTIAL not yet supported");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
return PointerGetDatum(NULL);
}
/*
* Never reached
*/
- elog(ERROR, "internal error #10 in ri_triggers.c");
+ elog(ERROR, "invalid match_type");
return PointerGetDatum(NULL);
}
@@ -2425,16 +2305,8 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
*/
ri_CheckTrigger(fcinfo, "RI_FKey_setdefault_upd", RI_TRIGTYPE_UPDATE);
- /*
- * Check for the correct # of call arguments
- */
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_setdefault_upd()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_setdefault_upd()",
- RI_MAX_NUMKEYS);
/*
* Nothing to do if no column names to compare given
@@ -2449,12 +2321,6 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
* fk_rel is opened in RowExclusiveLock mode since that's what our
* eventual UPDATE will get on it.
*/
- if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
-
fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock);
pk_rel = trigdata->tg_relation;
new_row = trigdata->tg_newtuple;
@@ -2509,7 +2375,7 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
}
if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect() failed in RI_FKey_setdefault_upd()");
+ elog(ERROR, "SPI_connect failed");
/*
* Prepare a plan for the set default delete operation.
@@ -2612,7 +2478,7 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish() failed in RI_FKey_setdefault_upd()");
+ elog(ERROR, "SPI_finish failed");
heap_close(fk_rel, RowExclusiveLock);
@@ -2632,14 +2498,16 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
* Handle MATCH PARTIAL set null delete.
*/
case RI_MATCH_TYPE_PARTIAL:
- elog(ERROR, "MATCH PARTIAL not yet supported");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
return PointerGetDatum(NULL);
}
/*
* Never reached
*/
- elog(ERROR, "internal error #11 in ri_triggers.c");
+ elog(ERROR, "invalid match_type");
return PointerGetDatum(NULL);
}
@@ -2669,11 +2537,13 @@ RI_FKey_keyequal_upd(TriggerData *trigdata)
*/
tgnargs = trigdata->tg_trigger->tgnargs;
tgargs = trigdata->tg_trigger->tgargs;
- if (tgnargs < 4 || (tgnargs % 2) != 0)
- elog(ERROR, "wrong # of arguments in call to RI_FKey_keyequal_upd()");
- if (tgnargs > RI_MAX_ARGUMENTS)
- elog(ERROR, "too many keys (%d max) in call to RI_FKey_keyequal_upd()",
- RI_MAX_NUMKEYS);
+ if (tgnargs < 4 ||
+ tgnargs > RI_MAX_ARGUMENTS ||
+ (tgnargs % 2) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
+ errmsg("%s() called with wrong number of trigger arguments",
+ "RI_FKey_keyequal_upd")));
/*
* Nothing to do if no column names to compare given
@@ -2688,10 +2558,12 @@ RI_FKey_keyequal_upd(TriggerData *trigdata)
* Use minimal locking for fk_rel here.
*/
if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
- elog(ERROR, "No target table given for trigger \"%s\" on \"%s\""
- "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT",
- trigdata->tg_trigger->tgname,
- RelationGetRelationName(trigdata->tg_relation));
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("no target table given for trigger \"%s\" on \"%s\"",
+ trigdata->tg_trigger->tgname,
+ RelationGetRelationName(trigdata->tg_relation)),
+ errhint("Remove this RI trigger and its mates, then do ALTER TABLE ADD CONSTRAINT.")));
fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, AccessShareLock);
pk_rel = trigdata->tg_relation;
@@ -2722,14 +2594,16 @@ RI_FKey_keyequal_upd(TriggerData *trigdata)
* Handle MATCH PARTIAL set null delete.
*/
case RI_MATCH_TYPE_PARTIAL:
- elog(ERROR, "MATCH PARTIAL not yet supported");
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MATCH PARTIAL not yet implemented")));
break;
}
/*
* Never reached
*/
- elog(ERROR, "internal error #12 in ri_triggers.c");
+ elog(ERROR, "invalid match_type");
return false;
}
@@ -2794,7 +2668,7 @@ ri_DetermineMatchType(char *str)
if (strcmp(str, "PARTIAL") == 0)
return RI_MATCH_TYPE_PARTIAL;
- elog(ERROR, "unrecognized referential integrity MATCH type '%s'", str);
+ elog(ERROR, "unrecognized referential integrity match type \"%s\"", str);
return 0;
}
@@ -2844,18 +2718,22 @@ ri_BuildQueryKeyFull(RI_QueryKey *key, Oid constr_id, int32 constr_queryno,
{
fno = SPI_fnumber(fk_rel->rd_att, argv[j]);
if (fno == SPI_ERROR_NOATTRIBUTE)
- elog(ERROR, "constraint %s: table %s does not have an attribute %s",
- argv[RI_CONSTRAINT_NAME_ARGNO],
- RelationGetRelationName(fk_rel),
- argv[j]);
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("table \"%s\" does not have attribute \"%s\" referenced by constraint \"%s\"",
+ RelationGetRelationName(fk_rel),
+ argv[j],
+ argv[RI_CONSTRAINT_NAME_ARGNO])));
key->keypair[i][RI_KEYPAIR_FK_IDX] = fno;
fno = SPI_fnumber(pk_rel->rd_att, argv[j + 1]);
if (fno == SPI_ERROR_NOATTRIBUTE)
- elog(ERROR, "constraint %s: table %s does not have an attribute %s",
- argv[RI_CONSTRAINT_NAME_ARGNO],
- RelationGetRelationName(pk_rel),
- argv[j + 1]);
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("table \"%s\" does not have attribute \"%s\" referenced by constraint \"%s\"",
+ RelationGetRelationName(pk_rel),
+ argv[j + 1],
+ argv[RI_CONSTRAINT_NAME_ARGNO])));
key->keypair[i][RI_KEYPAIR_PK_IDX] = fno;
}
}
@@ -2867,34 +2745,75 @@ static void
ri_CheckTrigger(FunctionCallInfo fcinfo, const char *funcname, int tgkind)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
+ int tgnargs;
if (!CALLED_AS_TRIGGER(fcinfo))
- elog(ERROR, "%s() not fired by trigger manager", funcname);
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
+ errmsg("%s() was not fired by trigger manager", funcname)));
+
+ /*
+ * Check proper event
+ */
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
- elog(ERROR, "%s() must be fired AFTER ROW", funcname);
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
+ errmsg("%s() must be fired AFTER ROW", funcname)));
switch (tgkind)
{
case RI_TRIGTYPE_INSERT:
if (!TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
- elog(ERROR, "%s() must be fired for INSERT", funcname);
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
+ errmsg("%s() must be fired for INSERT", funcname)));
break;
case RI_TRIGTYPE_UPDATE:
if (!TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
- elog(ERROR, "%s() must be fired for UPDATE", funcname);
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
+ errmsg("%s() must be fired for UPDATE", funcname)));
break;
case RI_TRIGTYPE_INUP:
if (!TRIGGER_FIRED_BY_INSERT(trigdata->tg_event) &&
!TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
- elog(ERROR, "%s() must be fired for INSERT or UPDATE",
- funcname);
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
+ errmsg("%s() must be fired for INSERT or UPDATE",
+ funcname)));
break;
case RI_TRIGTYPE_DELETE:
if (!TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
- elog(ERROR, "%s() must be fired for DELETE", funcname);
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
+ errmsg("%s() must be fired for DELETE", funcname)));
break;
}
+
+ /*
+ * Check for the correct # of call arguments
+ */
+ tgnargs = trigdata->tg_trigger->tgnargs;
+ if (tgnargs < 4 ||
+ tgnargs > RI_MAX_ARGUMENTS ||
+ (tgnargs % 2) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
+ errmsg("%s() called with wrong number of trigger arguments",
+ funcname)));
+
+ /*
+ * Check that tgconstrrelid is known. We need to check here because of
+ * ancient pg_dump bug; see notes in CreateTrigger().
+ */
+ if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("no target table given for trigger \"%s\" on \"%s\"",
+ trigdata->tg_trigger->tgname,
+ RelationGetRelationName(trigdata->tg_relation)),
+ errhint("Remove this RI trigger and its mates, then do ALTER TABLE ADD CONSTRAINT.")));
}
@@ -3025,7 +2944,7 @@ ri_PerformCheck(RI_QueryKey *qkey, void *qplan,
/* Check result */
if (spi_result < 0)
- elog(ERROR, "SPI_execp() failed in ri_PerformCheck()");
+ elog(ERROR, "SPI_execp failed");
if (expect_OK >= 0 && spi_result != expect_OK)
ri_ReportViolation(qkey, constrname ? constrname : "",
@@ -3069,9 +2988,9 @@ ri_ExtractValues(RI_QueryKey *qkey, int key_idx,
*
* If the failed constraint was on insert/update to the FK table,
* we want the key names and values extracted from there, and the error
- * message to look like 'key blah referenced from FK not found in PK'.
+ * message to look like 'key blah is not present in PK'.
* Otherwise, the attr names and values come from the PK table and the
- * message looks like 'key blah in PK still referenced from FK'.
+ * message looks like 'key blah is still referenced from FK'.
*/
static void
ri_ReportViolation(RI_QueryKey *qkey, const char *constrname,
@@ -3084,27 +3003,31 @@ ri_ReportViolation(RI_QueryKey *qkey, const char *constrname,
char *name_ptr = key_names;
char *val_ptr = key_values;
bool onfk;
- Relation rel,
- other_rel;
+ Relation rel;
int idx,
key_idx;
+ if (spi_err)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave unexpected result",
+ RelationGetRelationName(pk_rel),
+ constrname,
+ RelationGetRelationName(fk_rel)),
+ errhint("This is most likely due to a rule having rewritten the query.")));
+
/*
- * rel is set to where the tuple description is coming from, and it also
- * is the first relation mentioned in the message, other_rel is
- * respectively the other relation.
+ * rel is set to where the tuple description is coming from.
*/
onfk = (qkey->constr_queryno == RI_PLAN_CHECK_LOOKUPPK);
if (onfk)
{
rel = fk_rel;
- other_rel = pk_rel;
key_idx = RI_KEYPAIR_FK_IDX;
}
else
{
rel = pk_rel;
- other_rel = fk_rel;
key_idx = RI_KEYPAIR_PK_IDX;
}
@@ -3115,14 +3038,12 @@ ri_ReportViolation(RI_QueryKey *qkey, const char *constrname,
*/
if (qkey->nkeypairs == 0)
{
- if (spi_err)
- elog(ERROR, "%s referential action on %s from %s rewritten by rule",
- constrname,
- RelationGetRelationName(fk_rel),
- RelationGetRelationName(pk_rel));
- else
- elog(ERROR, "%s referential integrity violation - no rows found in %s",
- constrname, RelationGetRelationName(pk_rel));
+ ereport(ERROR,
+ (errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
+ errmsg("insert or update on \"%s\" violates foreign key constraint \"%s\"",
+ RelationGetRelationName(fk_rel), constrname),
+ errdetail("No rows were found in \"%s\".",
+ RelationGetRelationName(pk_rel))));
}
/* Get printable versions of the keys involved */
@@ -3151,24 +3072,25 @@ ri_ReportViolation(RI_QueryKey *qkey, const char *constrname,
name_ptr += sprintf(name_ptr, "%s%s", idx > 0 ? "," : "", name);
val_ptr += sprintf(val_ptr, "%s%s", idx > 0 ? "," : "", val);
- }
-
- if (spi_err)
- elog(ERROR, "%s referential action on %s from %s for (%s)=(%s) rewritten by rule",
- constrname,
- RelationGetRelationName(fk_rel),
- RelationGetRelationName(pk_rel),
- key_names, key_values);
- else if (onfk)
- elog(ERROR, "%s referential integrity violation - key (%s)=(%s) referenced from %s not found in %s",
- constrname, key_names, key_values,
- RelationGetRelationName(rel),
- RelationGetRelationName(other_rel));
- else
- elog(ERROR, "%s referential integrity violation - key (%s)=(%s) in %s still referenced from %s",
- constrname, key_names, key_values,
- RelationGetRelationName(rel),
- RelationGetRelationName(other_rel));
+ }
+
+ if (onfk)
+ ereport(ERROR,
+ (errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
+ errmsg("insert or update on \"%s\" violates foreign key constraint \"%s\"",
+ RelationGetRelationName(fk_rel), constrname),
+ errdetail("Key (%s)=(%s) is not present in \"%s\".",
+ key_names, key_values,
+ RelationGetRelationName(pk_rel))));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
+ errmsg("update or delete on \"%s\" violates foreign key constraint \"%s\" on \"%s\"",
+ RelationGetRelationName(pk_rel),
+ constrname, RelationGetRelationName(fk_rel)),
+ errdetail("Key (%s)=(%s) is still referenced from \"%s\".",
+ key_names, key_values,
+ RelationGetRelationName(fk_rel))));
}
/* ----------
@@ -3215,10 +3137,12 @@ ri_BuildQueryKeyPkCheck(RI_QueryKey *key, Oid constr_id, int32 constr_queryno,
{
fno = SPI_fnumber(pk_rel->rd_att, argv[j]);
if (fno == SPI_ERROR_NOATTRIBUTE)
- elog(ERROR, "constraint %s: table %s does not have an attribute %s",
- argv[RI_CONSTRAINT_NAME_ARGNO],
- RelationGetRelationName(pk_rel),
- argv[j + 1]);
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("table \"%s\" does not have attribute \"%s\" referenced by constraint \"%s\"",
+ RelationGetRelationName(pk_rel),
+ argv[j],
+ argv[RI_CONSTRAINT_NAME_ARGNO])));
key->keypair[i][RI_KEYPAIR_PK_IDX] = fno;
key->keypair[i][RI_KEYPAIR_FK_IDX] = 0;
}
@@ -3343,7 +3267,9 @@ ri_HashPreparedPlan(RI_QueryKey *key, void *plan)
(void *) key,
HASH_ENTER, &found);
if (entry == NULL)
- elog(ERROR, "out of memory for RI plan cache");
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
entry->plan = plan;
}
@@ -3532,7 +3458,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
/*
* Since fmgr_info could fail, call it *before* creating the
- * hashtable entry --- otherwise we could elog leaving an
+ * hashtable entry --- otherwise we could ereport leaving an
* incomplete entry in the hashtable. Also, because this will be
* a permanent table entry, we must make sure any subsidiary
* structures of the fmgr record are kept in TopMemoryContext.
@@ -3543,7 +3469,9 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
(void *) &typeid,
HASH_ENTER, &found);
if (entry == NULL)
- elog(ERROR, "out of memory for RI operator cache");
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
entry->typeid = typeid;
memcpy(&(entry->oprfmgrinfo), &finfo, sizeof(FmgrInfo));
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 732b0e7cfbd..661187269db 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: elog.h,v 1.54 2003/07/22 19:00:12 tgl Exp $
+ * $Id: elog.h,v 1.55 2003/07/22 22:14:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -162,7 +162,7 @@
#define ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION MAKE_SQLSTATE('2','3', '0','0','0')
#define ERRCODE_RESTRICT_VIOLATION MAKE_SQLSTATE('2','3', '0','0','1')
#define ERRCODE_NOT_NULL_VIOLATION MAKE_SQLSTATE('2','3', '5','0','2')
-#define ERRCODE_FOREIGN_KEY_VALUE_NOT_FOUND MAKE_SQLSTATE('2','3', '5','0','3')
+#define ERRCODE_FOREIGN_KEY_VIOLATION MAKE_SQLSTATE('2','3', '5','0','3')
#define ERRCODE_UNIQUE_VIOLATION MAKE_SQLSTATE('2','3', '5','0','5')
#define ERRCODE_CHECK_VIOLATION MAKE_SQLSTATE('2','3', '5','1','4')
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 677dce17ea5..19e60662c7f 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -316,7 +316,8 @@ ERROR: column "b" referenced in foreign key constraint does not exist
-- Try (and fail) to add constraint due to invalid data
ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full;
NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
-ERROR: tmpconstr referential integrity violation - key (a)=(5) referenced from tmp3 not found in tmp2
+ERROR: insert or update on "tmp3" violates foreign key constraint "tmpconstr"
+DETAIL: Key (a)=(5) is not present in "tmp2".
-- Delete failing row
DELETE FROM tmp3 where a=5;
-- Try (and succeed)
diff --git a/src/test/regress/expected/cluster.out b/src/test/regress/expected/cluster.out
index 50507fc961a..9a28df62d10 100644
--- a/src/test/regress/expected/cluster.out
+++ b/src/test/regress/expected/cluster.out
@@ -248,7 +248,8 @@ SELECT a,b,c,substring(d for 30), length(d) from clstr_tst;
-- Verify that foreign key link still works
INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail');
-ERROR: clstr_tst_con referential integrity violation - key (b)=(1111) referenced from clstr_tst not found in clstr_tst_s
+ERROR: insert or update on "clstr_tst" violates foreign key constraint "clstr_tst_con"
+DETAIL: Key (b)=(1111) is not present in "clstr_tst_s".
SELECT conname FROM pg_constraint WHERE conrelid = 'clstr_tst'::regclass;
conname
----------------
diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out
index 7ac2eb387d3..cb6fc35eb6d 100644
--- a/src/test/regress/expected/foreign_key.out
+++ b/src/test/regress/expected/foreign_key.out
@@ -22,7 +22,8 @@ INSERT INTO FKTABLE VALUES (3, 4);
INSERT INTO FKTABLE VALUES (NULL, 1);
-- Insert a failed row into FK TABLE
INSERT INTO FKTABLE VALUES (100, 2);
-ERROR: $1 referential integrity violation - key (ftest1)=(100) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "$1"
+DETAIL: Key (ftest1)=(100) is not present in "pktable".
-- Check FKTABLE
SELECT * FROM FKTABLE;
ftest1 | ftest2
@@ -80,13 +81,17 @@ INSERT INTO FKTABLE VALUES (3, 6, 12);
INSERT INTO FKTABLE VALUES (NULL, NULL, 0);
-- Insert failed rows into FK TABLE
INSERT INTO FKTABLE VALUES (100, 2, 4);
-ERROR: constrname referential integrity violation - key (ftest1,ftest2)=(100,2) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname"
+DETAIL: Key (ftest1,ftest2)=(100,2) is not present in "pktable".
INSERT INTO FKTABLE VALUES (2, 2, 4);
-ERROR: constrname referential integrity violation - key (ftest1,ftest2)=(2,2) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname"
+DETAIL: Key (ftest1,ftest2)=(2,2) is not present in "pktable".
INSERT INTO FKTABLE VALUES (NULL, 2, 4);
-ERROR: constrname referential integrity violation - MATCH FULL doesn't allow mixing of NULL and NON-NULL key values
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname"
+DETAIL: MATCH FULL does not allow mixing of NULL and non-NULL key values.
INSERT INTO FKTABLE VALUES (1, NULL, 4);
-ERROR: constrname referential integrity violation - MATCH FULL doesn't allow mixing of NULL and NON-NULL key values
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname"
+DETAIL: MATCH FULL does not allow mixing of NULL and non-NULL key values.
-- Check FKTABLE
SELECT * FROM FKTABLE;
ftest1 | ftest2 | ftest3
@@ -165,13 +170,17 @@ INSERT INTO FKTABLE VALUES (3, 6, 12);
INSERT INTO FKTABLE VALUES (NULL, NULL, 0);
-- Insert failed rows into FK TABLE
INSERT INTO FKTABLE VALUES (100, 2, 4);
-ERROR: constrname2 referential integrity violation - key (ftest1,ftest2)=(100,2) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname2"
+DETAIL: Key (ftest1,ftest2)=(100,2) is not present in "pktable".
INSERT INTO FKTABLE VALUES (2, 2, 4);
-ERROR: constrname2 referential integrity violation - key (ftest1,ftest2)=(2,2) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname2"
+DETAIL: Key (ftest1,ftest2)=(2,2) is not present in "pktable".
INSERT INTO FKTABLE VALUES (NULL, 2, 4);
-ERROR: constrname2 referential integrity violation - MATCH FULL doesn't allow mixing of NULL and NON-NULL key values
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname2"
+DETAIL: MATCH FULL does not allow mixing of NULL and non-NULL key values.
INSERT INTO FKTABLE VALUES (1, NULL, 4);
-ERROR: constrname2 referential integrity violation - MATCH FULL doesn't allow mixing of NULL and NON-NULL key values
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname2"
+DETAIL: MATCH FULL does not allow mixing of NULL and non-NULL key values.
-- Check FKTABLE
SELECT * FROM FKTABLE;
ftest1 | ftest2 | ftest3
@@ -250,7 +259,8 @@ INSERT INTO FKTABLE VALUES (3, 4);
INSERT INTO FKTABLE VALUES (NULL, 1);
-- Insert a failed row into FK TABLE
INSERT INTO FKTABLE VALUES (100, 2);
-ERROR: $1 referential integrity violation - key (ftest1)=(100) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "$1"
+DETAIL: Key (ftest1)=(100) is not present in "pktable".
-- Check FKTABLE
SELECT * FROM FKTABLE;
ftest1 | ftest2
@@ -274,7 +284,8 @@ SELECT * FROM PKTABLE;
-- Delete a row from PK TABLE (should fail)
DELETE FROM PKTABLE WHERE ptest1=1;
-ERROR: $1 referential integrity violation - key (ptest1)=(1) in pktable still referenced from fktable
+ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
+DETAIL: Key (ptest1)=(1) is still referenced from "fktable".
-- Delete a row from PK TABLE (should succeed)
DELETE FROM PKTABLE WHERE ptest1=5;
-- Check PKTABLE for deletes
@@ -289,7 +300,8 @@ SELECT * FROM PKTABLE;
-- Update a row from PK TABLE (should fail)
UPDATE PKTABLE SET ptest1=0 WHERE ptest1=2;
-ERROR: $1 referential integrity violation - key (ptest1)=(2) in pktable still referenced from fktable
+ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
+DETAIL: Key (ptest1)=(2) is still referenced from "fktable".
-- Update a row from PK TABLE (should succeed)
UPDATE PKTABLE SET ptest1=0 WHERE ptest1=4;
-- Check PKTABLE for updates
@@ -324,7 +336,8 @@ INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4);
INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5);
-- Insert a failed values
INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
-ERROR: constrname3 referential integrity violation - key (ftest1,ftest2,ftest3)=(1,2,7) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname3"
+DETAIL: Key (ftest1,ftest2,ftest3)=(1,2,7) is not present in "pktable".
-- Show FKTABLE
SELECT * from FKTABLE;
ftest1 | ftest2 | ftest3 | ftest4
@@ -338,12 +351,14 @@ SELECT * from FKTABLE;
-- Try to update something that should fail
UPDATE PKTABLE set ptest2=5 where ptest2=2;
-ERROR: constrname3 referential integrity violation - key (ptest1,ptest2,ptest3)=(1,2,3) in pktable still referenced from fktable
+ERROR: update or delete on "pktable" violates foreign key constraint "constrname3" on "fktable"
+DETAIL: Key (ptest1,ptest2,ptest3)=(1,2,3) is still referenced from "fktable".
-- Try to update something that should succeed
UPDATE PKTABLE set ptest1=1 WHERE ptest2=3;
-- Try to delete something that should fail
DELETE FROM PKTABLE where ptest1=1 and ptest2=2 and ptest3=3;
-ERROR: constrname3 referential integrity violation - key (ptest1,ptest2,ptest3)=(1,2,3) in pktable still referenced from fktable
+ERROR: update or delete on "pktable" violates foreign key constraint "constrname3" on "fktable"
+DETAIL: Key (ptest1,ptest2,ptest3)=(1,2,3) is still referenced from "fktable".
-- Try to delete something that should work
DELETE FROM PKTABLE where ptest1=2;
-- Show PKTABLE and FKTABLE
@@ -387,7 +402,8 @@ INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4);
INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5);
-- Insert a failed values
INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
-ERROR: constrname3 referential integrity violation - key (ftest1,ftest2,ftest3)=(1,2,7) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname3"
+DETAIL: Key (ftest1,ftest2,ftest3)=(1,2,7) is not present in "pktable".
-- Show FKTABLE
SELECT * from FKTABLE;
ftest1 | ftest2 | ftest3 | ftest4
@@ -485,7 +501,8 @@ INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4);
INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5);
-- Insert a failed values
INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
-ERROR: constrname3 referential integrity violation - key (ftest1,ftest2,ftest3)=(1,2,7) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname3"
+DETAIL: Key (ftest1,ftest2,ftest3)=(1,2,7) is not present in "pktable".
-- Show FKTABLE
SELECT * from FKTABLE;
ftest1 | ftest2 | ftest3 | ftest4
@@ -591,7 +608,8 @@ INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4);
INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5);
-- Insert a failed values
INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
-ERROR: constrname3 referential integrity violation - key (ftest1,ftest2,ftest3)=(1,2,7) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname3"
+DETAIL: Key (ftest1,ftest2,ftest3)=(1,2,7) is not present in "pktable".
-- Show FKTABLE
SELECT * from FKTABLE;
ftest1 | ftest2 | ftest3 | ftest4
@@ -607,7 +625,8 @@ SELECT * from FKTABLE;
-- Try to update something that will fail
UPDATE PKTABLE set ptest2=5 where ptest2=2;
-ERROR: constrname3 referential integrity violation - key (ftest1,ftest2,ftest3)=(1,-1,3) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "constrname3"
+DETAIL: Key (ftest1,ftest2,ftest3)=(1,-1,3) is not present in "pktable".
-- Try to update something that will set default
UPDATE PKTABLE set ptest1=0, ptest2=5, ptest3=10 where ptest2=2;
UPDATE PKTABLE set ptest2=10 where ptest2=4;
@@ -819,17 +838,20 @@ insert into pktable(base1) values (1);
insert into pktable(base1) values (2);
-- let's insert a non-existant fktable value
insert into fktable(ftest1) values (3);
-ERROR: $1 referential integrity violation - key (ftest1)=(3) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "$1"
+DETAIL: Key (ftest1)=(3) is not present in "pktable".
-- let's make a valid row for that
insert into pktable(base1) values (3);
insert into fktable(ftest1) values (3);
-- let's try removing a row that should fail from pktable
delete from pktable where base1>2;
-ERROR: $1 referential integrity violation - key (base1)=(3) in pktable still referenced from fktable
+ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
+DETAIL: Key (base1)=(3) is still referenced from "fktable".
-- okay, let's try updating all of the base1 values to *4
-- which should fail.
update pktable set base1=base1*4;
-ERROR: $1 referential integrity violation - key (base1)=(3) in pktable still referenced from fktable
+ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
+DETAIL: Key (base1)=(3) is still referenced from "fktable".
-- okay, let's try an update that should work.
update pktable set base1=base1*4 where base1<3;
-- and a delete that should work
@@ -845,17 +867,20 @@ insert into pktable(base1, ptest1) values (1, 1);
insert into pktable(base1, ptest1) values (2, 2);
-- let's insert a non-existant fktable value
insert into fktable(ftest1, ftest2) values (3, 1);
-ERROR: $1 referential integrity violation - key (ftest1,ftest2)=(3,1) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "$1"
+DETAIL: Key (ftest1,ftest2)=(3,1) is not present in "pktable".
-- let's make a valid row for that
insert into pktable(base1,ptest1) values (3, 1);
insert into fktable(ftest1, ftest2) values (3, 1);
-- let's try removing a row that should fail from pktable
delete from pktable where base1>2;
-ERROR: $1 referential integrity violation - key (base1,ptest1)=(3,1) in pktable still referenced from fktable
+ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
+DETAIL: Key (base1,ptest1)=(3,1) is still referenced from "fktable".
-- okay, let's try updating all of the base1 values to *4
-- which should fail.
update pktable set base1=base1*4;
-ERROR: $1 referential integrity violation - key (base1,ptest1)=(3,1) in pktable still referenced from fktable
+ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
+DETAIL: Key (base1,ptest1)=(3,1) is still referenced from "fktable".
-- okay, let's try an update that should work.
update pktable set base1=base1*4 where base1<3;
-- and a delete that should work
@@ -876,13 +901,16 @@ insert into pktable (base1, ptest1, base2, ptest2) values (2, 2, 2, 1);
insert into pktable (base1, ptest1, base2, ptest2) values (1, 3, 2, 2);
-- fails (3,2) isn't in base1, ptest1
insert into pktable (base1, ptest1, base2, ptest2) values (2, 3, 3, 2);
-ERROR: $1 referential integrity violation - key (base2,ptest2)=(3,2) referenced from pktable not found in pktable
+ERROR: insert or update on "pktable" violates foreign key constraint "$1"
+DETAIL: Key (base2,ptest2)=(3,2) is not present in "pktable".
-- fails (2,2) is being referenced
delete from pktable where base1=2;
-ERROR: $1 referential integrity violation - key (base1,ptest1)=(2,2) in pktable still referenced from pktable
+ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "pktable"
+DETAIL: Key (base1,ptest1)=(2,2) is still referenced from "pktable".
-- fails (1,1) is being referenced (twice)
update pktable set base1=3 where base1=1;
-ERROR: $1 referential integrity violation - key (base1,ptest1)=(1,1) in pktable still referenced from pktable
+ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "pktable"
+DETAIL: Key (base1,ptest1)=(1,1) is still referenced from "pktable".
-- this sequence of two deletes will work, since after the first there will be no (2,*) references
delete from pktable where base2=2;
delete from pktable where base1=2;
@@ -963,7 +991,8 @@ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "fktable_pkey" fo
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
-- default to immediate: should fail
INSERT INTO fktable VALUES (5, 10);
-ERROR: $1 referential integrity violation - key (fk)=(10) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "$1"
+DETAIL: Key (fk)=(10) is not present in "pktable".
-- explicitely defer the constraint
BEGIN;
SET CONSTRAINTS ALL DEFERRED;
@@ -993,7 +1022,8 @@ BEGIN;
SET CONSTRAINTS ALL IMMEDIATE;
-- should fail
INSERT INTO fktable VALUES (500, 1000);
-ERROR: $1 referential integrity violation - key (fk)=(1000) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "$1"
+DETAIL: Key (fk)=(1000) is not present in "pktable".
COMMIT;
DROP TABLE fktable, pktable;
-- tricky behavior: according to SQL99, if a deferred constraint is set
@@ -1017,7 +1047,8 @@ SET CONSTRAINTS ALL DEFERRED;
INSERT INTO fktable VALUES (1000, 2000);
-- should cause transaction abort, due to preceding error
SET CONSTRAINTS ALL IMMEDIATE;
-ERROR: $1 referential integrity violation - key (fk)=(2000) referenced from fktable not found in pktable
+ERROR: insert or update on "fktable" violates foreign key constraint "$1"
+DETAIL: Key (fk)=(2000) is not present in "pktable".
INSERT INTO pktable VALUES (2000, 3); -- too late
ERROR: current transaction is aborted, queries ignored until end of transaction block
COMMIT;