aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/explain.c32
-rw-r--r--src/backend/commands/trigger.c32
2 files changed, 52 insertions, 12 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index ef3d9beb062..048d12f97a2 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.190 2009/08/22 02:06:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.191 2009/10/10 01:43:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -581,6 +581,7 @@ ExplainNode(Plan *plan, PlanState *planstate,
const char *pname; /* node type name for text output */
const char *sname; /* node type name for non-text output */
const char *strategy = NULL;
+ const char *operation = NULL;
int save_indent = es->indent;
bool haschildren;
@@ -591,6 +592,24 @@ ExplainNode(Plan *plan, PlanState *planstate,
case T_Result:
pname = sname = "Result";
break;
+ case T_ModifyTable:
+ sname = "ModifyTable";
+ switch (((ModifyTable *) plan)->operation)
+ {
+ case CMD_INSERT:
+ pname = operation = "Insert";
+ break;
+ case CMD_UPDATE:
+ pname = operation = "Update";
+ break;
+ case CMD_DELETE:
+ pname = operation = "Delete";
+ break;
+ default:
+ pname = "???";
+ break;
+ }
+ break;
case T_Append:
pname = sname = "Append";
break;
@@ -736,6 +755,8 @@ ExplainNode(Plan *plan, PlanState *planstate,
ExplainPropertyText("Node Type", sname, es);
if (strategy)
ExplainPropertyText("Strategy", strategy, es);
+ if (operation)
+ ExplainPropertyText("Operation", operation, es);
if (relationship)
ExplainPropertyText("Parent Relationship", relationship, es);
if (plan_name)
@@ -1023,6 +1044,7 @@ ExplainNode(Plan *plan, PlanState *planstate,
haschildren = plan->initPlan ||
outerPlan(plan) ||
innerPlan(plan) ||
+ IsA(plan, ModifyTable) ||
IsA(plan, Append) ||
IsA(plan, BitmapAnd) ||
IsA(plan, BitmapOr) ||
@@ -1059,6 +1081,11 @@ ExplainNode(Plan *plan, PlanState *planstate,
/* special child plans */
switch (nodeTag(plan))
{
+ case T_ModifyTable:
+ ExplainMemberNodes(((ModifyTable *) plan)->plans,
+ ((ModifyTableState *) planstate)->mt_plans,
+ outer_plan, es);
+ break;
case T_Append:
ExplainMemberNodes(((Append *) plan)->appendplans,
((AppendState *) planstate)->appendplans,
@@ -1408,7 +1435,8 @@ ExplainScanTarget(Scan *plan, ExplainState *es)
}
/*
- * Explain the constituent plans of an Append, BitmapAnd, or BitmapOr node.
+ * Explain the constituent plans of a ModifyTable, Append, BitmapAnd,
+ * or BitmapOr node.
*
* Ordinarily we don't pass down outer_plan to our child nodes, but in these
* cases we must, since the node could be an "inner indexscan" in which case
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index c1f55cfcf93..47cf0c470d6 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.252 2009/08/04 16:08:36 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.253 2009/10/10 01:43:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -55,6 +55,7 @@ int SessionReplicationRole = SESSION_REPLICATION_ROLE_ORIGIN;
static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid);
static void InsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx);
static HeapTuple GetTupleForTrigger(EState *estate,
+ PlanState *subplanstate,
ResultRelInfo *relinfo,
ItemPointer tid,
TupleTableSlot **newSlot);
@@ -1793,7 +1794,8 @@ ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
}
bool
-ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
+ExecBRDeleteTriggers(EState *estate, PlanState *subplanstate,
+ ResultRelInfo *relinfo,
ItemPointer tupleid)
{
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
@@ -1806,7 +1808,8 @@ ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
TupleTableSlot *newSlot;
int i;
- trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
+ trigtuple = GetTupleForTrigger(estate, subplanstate, relinfo, tupleid,
+ &newSlot);
if (trigtuple == NULL)
return false;
@@ -1862,7 +1865,7 @@ ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
{
- HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
+ HeapTuple trigtuple = GetTupleForTrigger(estate, NULL, relinfo,
tupleid, NULL);
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE,
@@ -1941,7 +1944,8 @@ ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
}
HeapTuple
-ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
+ExecBRUpdateTriggers(EState *estate, PlanState *subplanstate,
+ ResultRelInfo *relinfo,
ItemPointer tupleid, HeapTuple newtuple)
{
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
@@ -1954,16 +1958,18 @@ ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
TupleTableSlot *newSlot;
int i;
- trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
+ trigtuple = GetTupleForTrigger(estate, subplanstate, relinfo, tupleid,
+ &newSlot);
if (trigtuple == NULL)
return NULL;
/*
* In READ COMMITTED isolation level it's possible that newtuple was
- * changed due to concurrent update.
+ * changed due to concurrent update. In that case we have a raw subplan
+ * output tuple and need to run it through the junk filter.
*/
if (newSlot != NULL)
- intuple = newtuple = ExecRemoveJunk(estate->es_junkFilter, newSlot);
+ intuple = newtuple = ExecRemoveJunk(relinfo->ri_junkFilter, newSlot);
LocTriggerData.type = T_TriggerData;
LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
@@ -2014,7 +2020,7 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
{
- HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
+ HeapTuple trigtuple = GetTupleForTrigger(estate, NULL, relinfo,
tupleid, NULL);
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
@@ -2094,7 +2100,9 @@ ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
static HeapTuple
-GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
+GetTupleForTrigger(EState *estate,
+ PlanState *subplanstate,
+ ResultRelInfo *relinfo,
ItemPointer tid,
TupleTableSlot **newSlot)
{
@@ -2111,6 +2119,9 @@ GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
*newSlot = NULL;
+ /* caller must pass a subplanstate if EvalPlanQual is possible */
+ Assert(subplanstate != NULL);
+
/*
* lock tuple for update
*/
@@ -2143,6 +2154,7 @@ ltrmark:;
epqslot = EvalPlanQual(estate,
relinfo->ri_RangeTableIndex,
+ subplanstate,
&update_ctid,
update_xmax);
if (!TupIsNull(epqslot))