mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Improve EXPLAIN ANALYZE to show the time spent in each trigger when
executing a statement that fires triggers. Formerly this time was included in "Total runtime" but not otherwise accounted for. As a side benefit, we avoid re-opening relations when firing non-deferred AFTER triggers, because the trigger code can re-use the main executor's ResultRelInfo data structure.
This commit is contained in:
@ -26,7 +26,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.243 2005/03/20 23:40:25 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.244 2005/03/25 21:57:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -39,6 +39,7 @@
|
||||
#include "commands/trigger.h"
|
||||
#include "executor/execdebug.h"
|
||||
#include "executor/execdefs.h"
|
||||
#include "executor/instrument.h"
|
||||
#include "miscadmin.h"
|
||||
#include "optimizer/clauses.h"
|
||||
#include "optimizer/var.h"
|
||||
@ -69,7 +70,8 @@ static void InitPlan(QueryDesc *queryDesc, bool explainOnly);
|
||||
static void initResultRelInfo(ResultRelInfo *resultRelInfo,
|
||||
Index resultRelationIndex,
|
||||
List *rangeTable,
|
||||
CmdType operation);
|
||||
CmdType operation,
|
||||
bool doInstrument);
|
||||
static TupleTableSlot *ExecutePlan(EState *estate, PlanState *planstate,
|
||||
CmdType operation,
|
||||
long numberTuples,
|
||||
@ -508,7 +510,8 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
|
||||
initResultRelInfo(resultRelInfo,
|
||||
lfirst_int(l),
|
||||
rangeTable,
|
||||
operation);
|
||||
operation,
|
||||
estate->es_instrument);
|
||||
resultRelInfo++;
|
||||
}
|
||||
}
|
||||
@ -523,7 +526,8 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
|
||||
initResultRelInfo(resultRelInfos,
|
||||
parseTree->resultRelation,
|
||||
rangeTable,
|
||||
operation);
|
||||
operation,
|
||||
estate->es_instrument);
|
||||
}
|
||||
|
||||
estate->es_result_relations = resultRelInfos;
|
||||
@ -798,7 +802,8 @@ static void
|
||||
initResultRelInfo(ResultRelInfo *resultRelInfo,
|
||||
Index resultRelationIndex,
|
||||
List *rangeTable,
|
||||
CmdType operation)
|
||||
CmdType operation,
|
||||
bool doInstrument)
|
||||
{
|
||||
Oid resultRelationOid;
|
||||
Relation resultRelationDesc;
|
||||
@ -837,7 +842,22 @@ initResultRelInfo(ResultRelInfo *resultRelInfo,
|
||||
resultRelInfo->ri_IndexRelationInfo = NULL;
|
||||
/* make a copy so as not to depend on relcache info not changing... */
|
||||
resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
|
||||
resultRelInfo->ri_TrigFunctions = NULL;
|
||||
if (resultRelInfo->ri_TrigDesc)
|
||||
{
|
||||
int n = resultRelInfo->ri_TrigDesc->numtriggers;
|
||||
|
||||
resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
|
||||
palloc0(n * sizeof(FmgrInfo));
|
||||
if (doInstrument)
|
||||
resultRelInfo->ri_TrigInstrument = InstrAlloc(n);
|
||||
else
|
||||
resultRelInfo->ri_TrigInstrument = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultRelInfo->ri_TrigFunctions = NULL;
|
||||
resultRelInfo->ri_TrigInstrument = NULL;
|
||||
}
|
||||
resultRelInfo->ri_ConstraintExprs = NULL;
|
||||
resultRelInfo->ri_junkFilter = NULL;
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.46 2004/12/31 21:59:45 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.47 2005/03/25 21:57:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -252,7 +252,7 @@ ExecInitNode(Plan *node, EState *estate)
|
||||
|
||||
/* Set up instrumentation for this node if requested */
|
||||
if (estate->es_instrument)
|
||||
result->instrument = InstrAlloc();
|
||||
result->instrument = InstrAlloc(1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.92 2005/03/16 21:38:07 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.93 2005/03/25 21:57:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -399,8 +399,8 @@ postquel_end(execution_state *es, SQLFunctionCachePtr fcache)
|
||||
{
|
||||
ActiveSnapshot = es->qd->snapshot;
|
||||
|
||||
AfterTriggerEndQuery(es->qd->estate);
|
||||
ExecutorEnd(es->qd);
|
||||
AfterTriggerEndQuery();
|
||||
}
|
||||
PG_CATCH();
|
||||
{
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/instrument.c,v 1.10 2005/03/20 22:27:51 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/instrument.c,v 1.11 2005/03/25 21:57:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -18,13 +18,13 @@
|
||||
#include "executor/instrument.h"
|
||||
|
||||
|
||||
/* Allocate new instrumentation structure */
|
||||
/* Allocate new instrumentation structure(s) */
|
||||
Instrumentation *
|
||||
InstrAlloc(void)
|
||||
InstrAlloc(int n)
|
||||
{
|
||||
Instrumentation *instr = palloc(sizeof(Instrumentation));
|
||||
Instrumentation *instr = palloc0(n * sizeof(Instrumentation));
|
||||
|
||||
memset(instr, 0, sizeof(Instrumentation));
|
||||
/* we don't need to do any initialization except zero 'em */
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.135 2005/03/16 21:38:08 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.136 2005/03/25 21:57:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1546,10 +1546,10 @@ _SPI_pquery(QueryDesc *queryDesc, int tcount)
|
||||
elog(ERROR, "consistency check on SPI tuple count failed");
|
||||
}
|
||||
|
||||
ExecutorEnd(queryDesc);
|
||||
|
||||
/* Take care of any queued AFTER triggers */
|
||||
AfterTriggerEndQuery();
|
||||
AfterTriggerEndQuery(queryDesc->estate);
|
||||
|
||||
ExecutorEnd(queryDesc);
|
||||
|
||||
if (queryDesc->dest->mydest == SPI)
|
||||
{
|
||||
|
Reference in New Issue
Block a user