diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2009-11-20 20:38:12 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2009-11-20 20:38:12 +0000 |
commit | 7fc0f06221d22632daa3ff8b70919b43e8a242ca (patch) | |
tree | a2ec73a6256c30ba9cb2d4723868978c5136ba5e /src/backend/executor | |
parent | 201a45c4fa23c485cf2e14ac9db8064b2c559fdc (diff) | |
download | postgresql-7fc0f06221d22632daa3ff8b70919b43e8a242ca.tar.gz postgresql-7fc0f06221d22632daa3ff8b70919b43e8a242ca.zip |
Add a WHEN clause to CREATE TRIGGER, allowing a boolean expression to be
checked to determine whether the trigger should be fired.
For BEFORE triggers this is mostly a matter of spec compliance; but for AFTER
triggers it can provide a noticeable performance improvement, since queuing of
a deferred trigger event and re-fetching of the row(s) at end of statement can
be short-circuited if the trigger does not need to be fired.
Takahiro Itagaki, reviewed by KaiGai Kohei.
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execMain.c | 6 | ||||
-rw-r--r-- | src/backend/executor/execQual.c | 55 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 3 | ||||
-rw-r--r-- | src/backend/executor/nodeModifyTable.c | 12 |
4 files changed, 54 insertions, 22 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index d7d99bc0aea..60ded334c68 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.334 2009/10/26 02:26:29 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.335 2009/11/20 20:38:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -752,6 +752,7 @@ InitPlan(QueryDesc *queryDesc, int eflags) */ estate->es_tupleTable = NIL; estate->es_trig_tuple_slot = NULL; + estate->es_trig_oldtup_slot = NULL; /* mark EvalPlanQual not active */ estate->es_epqTuple = NULL; @@ -911,6 +912,8 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo, resultRelInfo->ri_TrigFunctions = (FmgrInfo *) palloc0(n * sizeof(FmgrInfo)); + resultRelInfo->ri_TrigWhenExprs = (List **) + palloc0(n * sizeof(List *)); if (doInstrument) resultRelInfo->ri_TrigInstrument = InstrAlloc(n); else @@ -919,6 +922,7 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo, else { resultRelInfo->ri_TrigFunctions = NULL; + resultRelInfo->ri_TrigWhenExprs = NULL; resultRelInfo->ri_TrigInstrument = NULL; } resultRelInfo->ri_ConstraintExprs = NULL; diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 226e15546fd..36b72abcce2 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.254 2009/11/04 22:26:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.255 2009/11/20 20:38:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -491,26 +491,15 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext, if (isDone) *isDone = ExprSingleResult; - /* - * Get the input slot and attribute number we want - * - * The asserts check that references to system attributes only appear at - * the level of a relation scan; at higher levels, system attributes must - * be treated as ordinary variables (since we no longer have access to the - * original tuple). - */ - attnum = variable->varattno; - + /* Get the input slot and attribute number we want */ switch (variable->varno) { case INNER: /* get the tuple from the inner node */ slot = econtext->ecxt_innertuple; - Assert(attnum > 0); break; case OUTER: /* get the tuple from the outer node */ slot = econtext->ecxt_outertuple; - Assert(attnum > 0); break; default: /* get the tuple from the relation being @@ -519,6 +508,8 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext, break; } + attnum = variable->varattno; + if (attnum != InvalidAttrNumber) { /* @@ -715,7 +706,7 @@ ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone) { Var *variable = (Var *) exprstate->expr; - TupleTableSlot *slot = econtext->ecxt_scantuple; + TupleTableSlot *slot; HeapTuple tuple; TupleDesc tupleDesc; HeapTupleHeader dtuple; @@ -724,6 +715,23 @@ ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext, *isDone = ExprSingleResult; *isNull = false; + /* Get the input slot we want */ + switch (variable->varno) + { + case INNER: /* get the tuple from the inner node */ + slot = econtext->ecxt_innertuple; + break; + + case OUTER: /* get the tuple from the outer node */ + slot = econtext->ecxt_outertuple; + break; + + default: /* get the tuple from the relation being + * scanned */ + slot = econtext->ecxt_scantuple; + break; + } + tuple = ExecFetchSlotTuple(slot); tupleDesc = slot->tts_tupleDescriptor; @@ -766,7 +774,7 @@ ExecEvalWholeRowSlow(ExprState *exprstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone) { Var *variable = (Var *) exprstate->expr; - TupleTableSlot *slot = econtext->ecxt_scantuple; + TupleTableSlot *slot; HeapTuple tuple; TupleDesc var_tupdesc; HeapTupleHeader dtuple; @@ -775,6 +783,23 @@ ExecEvalWholeRowSlow(ExprState *exprstate, ExprContext *econtext, *isDone = ExprSingleResult; *isNull = false; + /* Get the input slot we want */ + switch (variable->varno) + { + case INNER: /* get the tuple from the inner node */ + slot = econtext->ecxt_innertuple; + break; + + case OUTER: /* get the tuple from the outer node */ + slot = econtext->ecxt_outertuple; + break; + + default: /* get the tuple from the relation being + * scanned */ + slot = econtext->ecxt_scantuple; + break; + } + /* * Currently, the only case handled here is stripping of trailing resjunk * fields, which we do in a slightly chintzy way by just adjusting the diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index d3352f1f5d4..e1aa8ce8ac9 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.165 2009/10/26 02:26:29 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.166 2009/11/20 20:38:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -117,6 +117,7 @@ CreateExecutorState(void) estate->es_trig_target_relations = NIL; estate->es_trig_tuple_slot = NULL; + estate->es_trig_oldtup_slot = NULL; estate->es_param_list_info = NULL; estate->es_param_exec_vals = NULL; diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 3f1f9c093ee..33b87cb63c0 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeModifyTable.c,v 1.2 2009/10/26 02:26:31 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeModifyTable.c,v 1.3 2009/11/20 20:38:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -215,9 +215,10 @@ ExecInsert(TupleTableSlot *slot, * slot should not try to clear it. */ TupleTableSlot *newslot = estate->es_trig_tuple_slot; + TupleDesc tupdesc = RelationGetDescr(resultRelationDesc); - if (newslot->tts_tupleDescriptor != slot->tts_tupleDescriptor) - ExecSetSlotDescriptor(newslot, slot->tts_tupleDescriptor); + if (newslot->tts_tupleDescriptor != tupdesc) + ExecSetSlotDescriptor(newslot, tupdesc); ExecStoreTuple(newtuple, newslot, InvalidBuffer, false); slot = newslot; tuple = newtuple; @@ -467,9 +468,10 @@ ExecUpdate(ItemPointer tupleid, * slot should not try to clear it. */ TupleTableSlot *newslot = estate->es_trig_tuple_slot; + TupleDesc tupdesc = RelationGetDescr(resultRelationDesc); - if (newslot->tts_tupleDescriptor != slot->tts_tupleDescriptor) - ExecSetSlotDescriptor(newslot, slot->tts_tupleDescriptor); + if (newslot->tts_tupleDescriptor != tupdesc) + ExecSetSlotDescriptor(newslot, tupdesc); ExecStoreTuple(newtuple, newslot, InvalidBuffer, false); slot = newslot; tuple = newtuple; |