|
|
|
@ -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.125 2002/08/13 17:22:08 petere Exp $ |
|
|
|
|
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.126 2002/08/17 12:15:48 momjian Exp $ |
|
|
|
|
* |
|
|
|
|
*------------------------------------------------------------------------- |
|
|
|
|
*/ |
|
|
|
@ -1266,12 +1266,10 @@ static MemoryContext deftrig_cxt = NULL; |
|
|
|
|
* state IMMEDIATE or DEFERRED. |
|
|
|
|
* ---------- |
|
|
|
|
*/ |
|
|
|
|
static bool deftrig_dfl_all_isset = false; |
|
|
|
|
static bool deftrig_dfl_all_isdeferred = false; |
|
|
|
|
static List *deftrig_dfl_trigstates = NIL; |
|
|
|
|
|
|
|
|
|
static bool deftrig_all_isset; |
|
|
|
|
static bool deftrig_all_isdeferred; |
|
|
|
|
static bool deftrig_all_isset = false; |
|
|
|
|
static bool deftrig_all_isdeferred = false; |
|
|
|
|
static List *deftrig_trigstates; |
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
@ -1702,8 +1700,11 @@ DeferredTriggerBeginXact(void) |
|
|
|
|
ALLOCSET_DEFAULT_MAXSIZE); |
|
|
|
|
oldcxt = MemoryContextSwitchTo(deftrig_cxt); |
|
|
|
|
|
|
|
|
|
deftrig_all_isset = deftrig_dfl_all_isset; |
|
|
|
|
deftrig_all_isdeferred = deftrig_dfl_all_isdeferred; |
|
|
|
|
deftrig_all_isset = false; |
|
|
|
|
/*
|
|
|
|
|
* If unspecified, constraints default to IMMEDIATE, per SQL |
|
|
|
|
*/ |
|
|
|
|
deftrig_all_isdeferred = false; |
|
|
|
|
|
|
|
|
|
deftrig_trigstates = NIL; |
|
|
|
|
foreach(l, deftrig_dfl_trigstates) |
|
|
|
@ -1793,59 +1794,30 @@ DeferredTriggerAbortXact(void) |
|
|
|
|
/* ----------
|
|
|
|
|
* DeferredTriggerSetState() |
|
|
|
|
* |
|
|
|
|
* Called for the users SET CONSTRAINTS ... utility command. |
|
|
|
|
* Called for the SET CONSTRAINTS ... utility command. |
|
|
|
|
* ---------- |
|
|
|
|
*/ |
|
|
|
|
void |
|
|
|
|
DeferredTriggerSetState(ConstraintsSetStmt *stmt) |
|
|
|
|
{ |
|
|
|
|
Relation tgrel; |
|
|
|
|
List *l; |
|
|
|
|
List *ls; |
|
|
|
|
List *loid = NIL; |
|
|
|
|
MemoryContext oldcxt; |
|
|
|
|
bool found; |
|
|
|
|
DeferredTriggerStatus state; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Handle SET CONSTRAINTS ALL ... |
|
|
|
|
* If called outside a transaction block, we can safely return: this |
|
|
|
|
* command cannot effect any subsequent transactions, and there |
|
|
|
|
* are no "session-level" trigger settings. |
|
|
|
|
*/ |
|
|
|
|
if (stmt->constraints == NIL) |
|
|
|
|
{ |
|
|
|
|
if (!IsTransactionBlock()) |
|
|
|
|
{ |
|
|
|
|
/*
|
|
|
|
|
* ... outside of a transaction block |
|
|
|
|
* |
|
|
|
|
* Drop all information about individual trigger states per |
|
|
|
|
* session. |
|
|
|
|
*/ |
|
|
|
|
l = deftrig_dfl_trigstates; |
|
|
|
|
while (l != NIL) |
|
|
|
|
{ |
|
|
|
|
List *next = lnext(l); |
|
|
|
|
|
|
|
|
|
pfree(lfirst(l)); |
|
|
|
|
pfree(l); |
|
|
|
|
l = next; |
|
|
|
|
} |
|
|
|
|
deftrig_dfl_trigstates = NIL; |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set the session ALL state to known. |
|
|
|
|
* Handle SET CONSTRAINTS ALL ... |
|
|
|
|
*/ |
|
|
|
|
deftrig_dfl_all_isset = true; |
|
|
|
|
deftrig_dfl_all_isdeferred = stmt->deferred; |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
if (stmt->constraints == NIL) |
|
|
|
|
{ |
|
|
|
|
/*
|
|
|
|
|
* ... inside of a transaction block |
|
|
|
|
* |
|
|
|
|
* Drop all information about individual trigger states per |
|
|
|
|
* transaction. |
|
|
|
|
* Drop all per-transaction information about individual trigger |
|
|
|
|
* states. |
|
|
|
|
*/ |
|
|
|
|
l = deftrig_trigstates; |
|
|
|
|
while (l != NIL) |
|
|
|
@ -1859,14 +1831,19 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt) |
|
|
|
|
deftrig_trigstates = NIL; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set the per transaction ALL state to known. |
|
|
|
|
* Set the per-transaction ALL state to known. |
|
|
|
|
*/ |
|
|
|
|
deftrig_all_isset = true; |
|
|
|
|
deftrig_all_isdeferred = stmt->deferred; |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
Relation tgrel; |
|
|
|
|
MemoryContext oldcxt; |
|
|
|
|
bool found; |
|
|
|
|
DeferredTriggerStatus state; |
|
|
|
|
List *ls; |
|
|
|
|
List *loid = NIL; |
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
|
* Handle SET CONSTRAINTS constraint-name [, ...] |
|
|
|
@ -1891,8 +1868,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt) |
|
|
|
|
/*
|
|
|
|
|
* Setup to scan pg_trigger by tgconstrname ... |
|
|
|
|
*/ |
|
|
|
|
ScanKeyEntryInitialize(&skey, |
|
|
|
|
(bits16) 0x0, |
|
|
|
|
ScanKeyEntryInitialize(&skey, (bits16) 0x0, |
|
|
|
|
(AttrNumber) Anum_pg_trigger_tgconstrname, |
|
|
|
|
(RegProcedure) F_NAMEEQ, |
|
|
|
|
PointerGetDatum(cname)); |
|
|
|
@ -1937,45 +1913,6 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt) |
|
|
|
|
} |
|
|
|
|
heap_close(tgrel, AccessShareLock); |
|
|
|
|
|
|
|
|
|
if (!IsTransactionBlock()) |
|
|
|
|
{ |
|
|
|
|
/*
|
|
|
|
|
* Outside of a transaction block set the trigger states of |
|
|
|
|
* individual triggers on session level. |
|
|
|
|
*/ |
|
|
|
|
oldcxt = MemoryContextSwitchTo(deftrig_gcxt); |
|
|
|
|
|
|
|
|
|
foreach(l, loid) |
|
|
|
|
{ |
|
|
|
|
found = false; |
|
|
|
|
foreach(ls, deftrig_dfl_trigstates) |
|
|
|
|
{ |
|
|
|
|
state = (DeferredTriggerStatus) lfirst(ls); |
|
|
|
|
if (state->dts_tgoid == (Oid) lfirsti(l)) |
|
|
|
|
{ |
|
|
|
|
state->dts_tgisdeferred = stmt->deferred; |
|
|
|
|
found = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!found) |
|
|
|
|
{ |
|
|
|
|
state = (DeferredTriggerStatus) |
|
|
|
|
palloc(sizeof(DeferredTriggerStatusData)); |
|
|
|
|
state->dts_tgoid = (Oid) lfirsti(l); |
|
|
|
|
state->dts_tgisdeferred = stmt->deferred; |
|
|
|
|
|
|
|
|
|
deftrig_dfl_trigstates = |
|
|
|
|
lappend(deftrig_dfl_trigstates, state); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MemoryContextSwitchTo(oldcxt); |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
/*
|
|
|
|
|
* Inside of a transaction block set the trigger states of |
|
|
|
|
* individual triggers on transaction level. |
|
|
|
@ -2008,9 +1945,17 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MemoryContextSwitchTo(oldcxt); |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* SQL99 requires that when a constraint is set to IMMEDIATE, any |
|
|
|
|
* deferred checks against that constraint must be made when the |
|
|
|
|
* SET CONSTRAINTS command is executed -- i.e. the effects of the |
|
|
|
|
* SET CONSTRAINTS command applies retroactively. This happens "for |
|
|
|
|
* free" since we have already made the necessary modifications to |
|
|
|
|
* the constraints, and deferredTriggerEndQuery() is called by |
|
|
|
|
* finish_xact_command(). |
|
|
|
|
*/ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|