Add tgconstrrelid to stored Trigger structures, make RI trigger functions

depend on this rather than the trigger argument strings to locate the
other relation to test.  This makes RI triggers function properly in
the presence of schemas and temp tables.  Along the way, fix bogus lack
of locking in RI triggers, handle quoting of names fully correctly,
compute required sizes of query buffers with some semblance of accuracy.
This commit is contained in:
Tom Lane 2002-04-01 22:36:13 +00:00
parent 6a25cd6b26
commit 789ddcb5fe
6 changed files with 370 additions and 254 deletions

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.21 2002/03/22 19:20:32 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.22 2002/04/01 22:36:06 tgl Exp $
-->
<chapter id="triggers">
@ -374,6 +374,7 @@ typedef struct Trigger
int16 tgtype;
bool tgenabled;
bool tgisconstraint;
Oid tgconstrrelid;
bool tgdeferrable;
bool tginitdeferred;
int16 tgnargs;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.170 2002/04/01 04:35:38 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.171 2002/04/01 22:36:09 tgl Exp $
*
* NOTES
* The PerformAddAttribute() code, like most of the relation
@ -1639,9 +1639,6 @@ AlterTableAddConstraint(Oid myrelid,
!isTempNamespace(RelationGetNamespace(rel)))
elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
/* Don't need pkrel open anymore, but hold lock */
heap_close(pkrel, NoLock);
/*
* First we check for limited correctness of the
* constraint.
@ -1651,34 +1648,30 @@ AlterTableAddConstraint(Oid myrelid,
* referenced relation, and that the column datatypes
* are comparable.
*
* Scan through each tuple, calling the RI_FKey_Match_Ins
* Scan through each tuple, calling RI_FKey_check_ins
* (insert trigger) as if that tuple had just been
* inserted. If any of those fail, it should
* elog(ERROR) and that's that.
*/
trig.tgoid = 0;
MemSet(&trig, 0, sizeof(trig));
trig.tgoid = InvalidOid;
if (fkconstraint->constr_name)
trig.tgname = fkconstraint->constr_name;
else
trig.tgname = "<unknown>";
trig.tgfoid = 0;
trig.tgtype = 0;
trig.tgenabled = TRUE;
trig.tgisconstraint = TRUE;
trig.tginitdeferred = FALSE;
trig.tgconstrrelid = RelationGetRelid(pkrel);
trig.tgdeferrable = FALSE;
trig.tginitdeferred = FALSE;
trig.tgargs = (char **) palloc(
sizeof(char *) * (4 + length(fkconstraint->fk_attrs)
+ length(fkconstraint->pk_attrs)));
if (fkconstraint->constr_name)
trig.tgargs[0] = fkconstraint->constr_name;
else
trig.tgargs[0] = "<unknown>";
trig.tgargs[1] = pstrdup(RelationGetRelationName(rel));
trig.tgargs[2] = fkconstraint->pktable->relname;
trig.tgargs[0] = trig.tgname;
trig.tgargs[1] = RelationGetRelationName(rel);
trig.tgargs[2] = RelationGetRelationName(pkrel);
trig.tgargs[3] = fkconstraint->match_type;
count = 4;
foreach(list, fkconstraint->fk_attrs)
@ -1732,6 +1725,9 @@ AlterTableAddConstraint(Oid myrelid,
heap_endscan(scan);
pfree(trig.tgargs);
heap_close(pkrel, NoLock);
break;
}
default:

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.110 2002/03/31 06:26:30 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.111 2002/04/01 22:36:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -544,6 +544,7 @@ RelationBuildTriggers(Relation relation)
build->tgtype = pg_trigger->tgtype;
build->tgenabled = pg_trigger->tgenabled;
build->tgisconstraint = pg_trigger->tgisconstraint;
build->tgconstrrelid = pg_trigger->tgconstrrelid;
build->tgdeferrable = pg_trigger->tgdeferrable;
build->tginitdeferred = pg_trigger->tginitdeferred;
build->tgnargs = pg_trigger->tgnargs;
@ -763,6 +764,8 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
return false;
if (trig1->tgisconstraint != trig2->tgisconstraint)
return false;
if (trig1->tgconstrrelid != trig2->tgconstrrelid)
return false;
if (trig1->tgdeferrable != trig2->tgdeferrable)
return false;
if (trig1->tginitdeferred != trig2->tginitdeferred)

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: trigger.h,v 1.33 2002/03/29 22:10:34 tgl Exp $
* $Id: trigger.h,v 1.34 2002/04/01 22:36:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -81,6 +81,12 @@ typedef struct TriggerData
* constrname\0fkrel\0pkrel\0matchtype\0fkatt\0pkatt\0fkatt\0pkatt\0...
*
* There are one or more pairs of fkatt/pkatt names.
*
* The relation names are no longer of much use since they are not
* guaranteed unique; they are present only for backwards compatibility.
* Use the tgrelid and tgconstrrelid fields to identify the referenced
* relations, instead. (But note that which is which will depend on which
* trigger you are looking at!)
*/
#define RI_CONSTRAINT_NAME_ARGNO 0
#define RI_FK_RELNAME_ARGNO 1
@ -127,9 +133,8 @@ extern void ExecARUpdateTriggers(EState *estate,
HeapTuple newtuple);
/* ----------
/*
* Deferred trigger stuff
* ----------
*/
typedef struct DeferredTriggerStatusData
{
@ -139,14 +144,12 @@ typedef struct DeferredTriggerStatusData
typedef struct DeferredTriggerStatusData *DeferredTriggerStatus;
typedef struct DeferredTriggerEventItem
{
Oid dti_tgoid;
int32 dti_state;
} DeferredTriggerEventItem;
typedef struct DeferredTriggerEventData *DeferredTriggerEvent;
typedef struct DeferredTriggerEventData
@ -173,7 +176,6 @@ extern void DeferredTriggerSetState(ConstraintsSetStmt *stmt);
/*
* in utils/adt/ri_triggers.c
*
*/
extern bool RI_FKey_keyequal_upd(TriggerData *trigdata);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: rel.h,v 1.58 2002/03/31 06:26:32 tgl Exp $
* $Id: rel.h,v 1.59 2002/04/01 22:36:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -49,12 +49,14 @@ typedef LockInfoData *LockInfo;
*/
typedef struct Trigger
{
Oid tgoid;
Oid tgoid; /* OID of trigger (pg_trigger row) */
/* Remaining fields are copied from pg_trigger, see pg_trigger.h */
char *tgname;
Oid tgfoid;
int16 tgtype;
bool tgenabled;
bool tgisconstraint;
Oid tgconstrrelid;
bool tgdeferrable;
bool tginitdeferred;
int16 tgnargs;