From 5ffb00497dc76b2289c1e03167ce70e2dcf7b85a Mon Sep 17 00:00:00 2001 From: EC2 Default User Date: Wed, 5 Apr 2023 04:00:52 +0000 Subject: [PATCH 1/1] Fix row tracking in pg_stat_statements. In pg_stat_statements, EState->es_processed cannot reliably be used to count the rows processed for a statement that goes through extended query protocol. This is because, such a statement may execute a portal more than once, and es_processed is reset after every execution. This fix addresses this issue by accuumulating the # row processed for all the executions of a portal. Author: Sami Imseih Discussion: https://www.postgresql.org/message-id/flat/EBE6C507-9EB6-4142-9E4D-38B1673363A7%40amazon.com --- contrib/pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/executor/execMain.c | 5 ++++- src/include/nodes/execnodes.h | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 5285c3f7fa..68215bb2e3 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1060,7 +1060,7 @@ pgss_ExecutorEnd(QueryDesc *queryDesc) queryDesc->plannedstmt->stmt_len, PGSS_EXEC, queryDesc->totaltime->total * 1000.0, /* convert to msec */ - queryDesc->estate->es_processed, + queryDesc->estate->es_total_processed, &queryDesc->totaltime->bufusage, &queryDesc->totaltime->walusage, queryDesc->estate->es_jit ? &queryDesc->estate->es_jit->instr : NULL, diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 1b007dc32c..4c97ffd910 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -289,7 +289,8 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags) * There is no return value, but output tuples (if any) are sent to * the destination receiver specified in the QueryDesc; and the number * of tuples processed at the top level can be found in - * estate->es_processed. + * estate->es_processed. The total tuples processed in all + * ExecutorRun calls can be found in estate->es_total_processed. * * We provide a function hook variable that lets loadable plugins * get control when ExecutorRun is called. Such a plugin would @@ -372,6 +373,8 @@ standard_ExecutorRun(QueryDesc *queryDesc, execute_once); } + estate->es_total_processed += estate->es_processed; + /* * shutdown tuple receiver, if we started it */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index d97f5a8e7d..ee456ab2cb 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -661,7 +661,10 @@ typedef struct EState List *es_tupleTable; /* List of TupleTableSlots */ - uint64 es_processed; /* # of tuples processed */ + uint64 es_processed; /* # of tuples processed during + * one ExecutorRun() call. */ + uint64 es_total_processed; /* total # of tuples aggregated across + * all ExecutorRun() calls. */ int es_top_eflags; /* eflags passed to ExecutorStart */ int es_instrument; /* OR of InstrumentOption flags */ -- 2.39.2