diff options
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r-- | src/backend/commands/explain.c | 73 |
1 files changed, 67 insertions, 6 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 02c9534cab8..02ceedd3959 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.130 2005/03/20 22:27:51 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.131 2005/03/25 21:57:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -15,6 +15,7 @@ #include "access/genam.h" #include "access/heapam.h" +#include "catalog/pg_constraint.h" #include "catalog/pg_type.h" #include "commands/explain.h" #include "commands/prepare.h" @@ -272,16 +273,76 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt, } /* - * Close down the query and free resources; also run any queued - * AFTER triggers. Include time for this in the total runtime. + * If we ran the command, run any AFTER triggers it queued. (Note this + * will not include DEFERRED triggers; since those don't run until end of + * transaction, we can't measure them.) Include into total runtime. + */ + if (stmt->analyze) + { + INSTR_TIME_SET_CURRENT(starttime); + AfterTriggerEndQuery(queryDesc->estate); + totaltime += elapsed_time(&starttime); + } + + /* Print info about runtime of triggers */ + if (es->printAnalyze) + { + ResultRelInfo *rInfo; + int numrels = queryDesc->estate->es_num_result_relations; + int nr; + + rInfo = queryDesc->estate->es_result_relations; + for (nr = 0; nr < numrels; rInfo++, nr++) + { + int nt; + + if (!rInfo->ri_TrigDesc) + continue; + for (nt = 0; nt < rInfo->ri_TrigDesc->numtriggers; nt++) + { + Trigger *trig = rInfo->ri_TrigDesc->triggers + nt; + Instrumentation *instr = rInfo->ri_TrigInstrument + nt; + char *conname; + + /* Must clean up instrumentation state */ + InstrEndLoop(instr); + + /* + * We ignore triggers that were never invoked; they likely + * aren't relevant to the current query type. + */ + if (instr->ntuples == 0) + continue; + + if (trig->tgisconstraint && + (conname = GetConstraintNameForTrigger(trig->tgoid)) != NULL) + { + appendStringInfo(str, "Trigger for constraint %s", + conname); + pfree(conname); + } + else + appendStringInfo(str, "Trigger %s", trig->tgname); + + if (numrels > 1) + appendStringInfo(str, " on %s", + RelationGetRelationName(rInfo->ri_RelationDesc)); + + appendStringInfo(str, ": time=%.3f calls=%.0f\n", + 1000.0 * instr->total, + instr->ntuples); + } + } + } + + /* + * Close down the query and free resources. Include time for this + * in the total runtime (although it should be pretty minimal). */ INSTR_TIME_SET_CURRENT(starttime); ExecutorEnd(queryDesc); - if (stmt->analyze) - AfterTriggerEndQuery(); - FreeQueryDesc(queryDesc); /* We need a CCI just in case query expanded to multiple plans */ |