Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
56f87688
Commit
56f87688
authored
Jul 22, 2003
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Error message editing for foreign-key triggers.
parent
fe5de484
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
280 additions
and
319 deletions
+280
-319
src/backend/utils/adt/ri_triggers.c
src/backend/utils/adt/ri_triggers.c
+212
-284
src/include/utils/elog.h
src/include/utils/elog.h
+2
-2
src/test/regress/expected/alter_table.out
src/test/regress/expected/alter_table.out
+2
-1
src/test/regress/expected/cluster.out
src/test/regress/expected/cluster.out
+2
-1
src/test/regress/expected/foreign_key.out
src/test/regress/expected/foreign_key.out
+62
-31
No files found.
src/backend/utils/adt/ri_triggers.c
View file @
56f87688
...
...
@@ -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.5
1 2003/06/11 15:02:25 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.5
2 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\t
Remove 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\t
Remove 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
,
"in
ternal error #2 in ri_triggers.c
"
);
elog
(
ERROR
,
"in
valid 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\t
Remove 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
,
"in
ternal error #3 in ri_triggers.c
"
);
elog
(
ERROR
,
"in
valid 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\t
Remove 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
,
"in
ternal error #4 in ri_triggers.c
"
);
elog
(
ERROR
,
"in
valid 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\t
Remove 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
,
"in
ternal error #5 in ri_triggers.c
"
);
elog
(
ERROR
,
"in
valid 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\t
Remove 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
,
"in
ternal error #6 in ri_triggers.c
"
);
elog
(
ERROR
,
"in
valid 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\t
Remove 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
,
"in
ternal error #7 in ri_triggers.c
"
);
elog
(
ERROR
,
"in
valid 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\t
Remove 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
,
"in
ternal error #8 in ri_triggers.c
"
);
elog
(
ERROR
,
"in
valid 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\t
Remove 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
,
"in
ternal error #9 in ri_triggers.c
"
);
elog
(
ERROR
,
"in
valid 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\t
Remove 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
,
"in
ternal error #10 in ri_triggers.c
"
);
elog
(
ERROR
,
"in
valid 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\t
Remove 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
,
"in
ternal error #11 in ri_triggers.c
"
);
elog
(
ERROR
,
"in
valid 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\t
Remove 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
,
"in
ternal error #12 in ri_triggers.c
"
);
elog
(
ERROR
,
"in
valid 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 i
n PK
still referenced from FK'.
* message looks like 'key blah i
s
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 e
log
leaving an
* hashtable entry --- otherwise we could e
report
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
));
...
...
src/include/utils/elog.h
View file @
56f87688
...
...
@@ -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.5
4 2003/07/22 19:00:12
tgl Exp $
* $Id: elog.h,v 1.5
5 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_V
ALUE_NOT_FOUND
MAKE_SQLSTATE('2','3', '5','0','3')
#define ERRCODE_FOREIGN_KEY_V
IOLATION
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')
...
...
src/test/regress/expected/alter_table.out
View file @
56f87688
...
...
@@ -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)
...
...
src/test/regress/expected/cluster.out
View file @
56f87688
...
...
@@ -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
----------------
...
...
src/test/regress/expected/foreign_key.out
View file @
56f87688
...
...
@@ -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;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment