Skip to content

Commit 2a0cd38

Browse files
committed
Allow plugins to set a 64-bit plan identifier in PlannedStmt
This field can be optionally set in a PlannedStmt through the planner hook, giving extensions the possibility to assign an identifier related to a computed plan. The backend is changed to report it in the backend entry of a process running (including the extended query protocol), with semantics and APIs to set or get it similar to what is used for the existing query ID (introduced in the backend via 4f0b096). The plan ID is reset at the same timing as the query ID. Currently, this information is not added to the system view pg_stat_activity; extensions can access it through PgBackendStatus. Some patches have been proposed to provide some features in the planning area, where a plan identifier is used as a key to know the plan involved (for statistics, plan storage and manipulations, etc.), and the point of this commit is to provide an anchor in the backend that extensions can rely on for future work. The reset of the plan identifier is controlled by core and follows the same pattern as the query identifier added in 4f0b096. The contents of this commit are extracted from a larger set proposed originally by Lukas Fittl, that Sami Imseih has proposed as an independent change, with a few tweaks sprinkled by me. Author: Lukas Fittl <lukas@fittl.com> Author: Sami Imseih <samimseih@gmail.com> Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com> Reviewed-by: Michael Paquier <michael@paquier.xyz> Discussion: https://postgr.es/m/CAP53Pkyow59ajFMHGpmb1BK9WHDypaWtUsS_5DoYUEfsa_Hktg@mail.gmail.com Discussion: https://postgr.es/m/CAA5RZ0vyWd4r35uUBUmhngv8XqeiJUkJDDKkLf5LCoWxv-t_pw@mail.gmail.com
1 parent 8a3e401 commit 2a0cd38

File tree

6 files changed

+95
-0
lines changed

6 files changed

+95
-0
lines changed

src/backend/executor/execParallel.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ ExecSerializePlan(Plan *plan, EState *estate)
175175
pstmt = makeNode(PlannedStmt);
176176
pstmt->commandType = CMD_SELECT;
177177
pstmt->queryId = pgstat_get_my_query_id();
178+
pstmt->planId = pgstat_get_my_plan_id();
178179
pstmt->hasReturning = false;
179180
pstmt->hasModifyingCTE = false;
180181
pstmt->canSetTag = true;

src/backend/optimizer/plan/planner.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include "parser/parsetree.h"
5959
#include "partitioning/partdesc.h"
6060
#include "rewrite/rewriteManip.h"
61+
#include "utils/backend_status.h"
6162
#include "utils/lsyscache.h"
6263
#include "utils/rel.h"
6364
#include "utils/selfuncs.h"
@@ -291,6 +292,9 @@ planner(Query *parse, const char *query_string, int cursorOptions,
291292
result = (*planner_hook) (parse, query_string, cursorOptions, boundParams);
292293
else
293294
result = standard_planner(parse, query_string, cursorOptions, boundParams);
295+
296+
pgstat_report_plan_id(result->planId, false);
297+
294298
return result;
295299
}
296300

src/backend/tcop/postgres.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,7 @@ exec_simple_query(const char *query_string)
11071107
size_t cmdtaglen;
11081108

11091109
pgstat_report_query_id(0, true);
1110+
pgstat_report_plan_id(0, true);
11101111

11111112
/*
11121113
* Get the command name for use in status display (it also becomes the
@@ -2030,6 +2031,18 @@ exec_bind_message(StringInfo input_message)
20302031
cplan,
20312032
psrc);
20322033

2034+
/* Portal is defined, set the plan ID based on its contents. */
2035+
foreach(lc, portal->stmts)
2036+
{
2037+
PlannedStmt *plan = lfirst_node(PlannedStmt, lc);
2038+
2039+
if (plan->planId != UINT64CONST(0))
2040+
{
2041+
pgstat_report_plan_id(plan->planId, false);
2042+
break;
2043+
}
2044+
}
2045+
20332046
/* Done with the snapshot used for parameter I/O and parsing/planning */
20342047
if (snapshot_set)
20352048
PopActiveSnapshot();
@@ -2170,6 +2183,17 @@ exec_execute_message(const char *portal_name, long max_rows)
21702183
}
21712184
}
21722185

2186+
foreach(lc, portal->stmts)
2187+
{
2188+
PlannedStmt *stmt = lfirst_node(PlannedStmt, lc);
2189+
2190+
if (stmt->planId != UINT64CONST(0))
2191+
{
2192+
pgstat_report_plan_id(stmt->planId, false);
2193+
break;
2194+
}
2195+
}
2196+
21732197
cmdtagname = GetCommandTagNameAndLen(portal->commandTag, &cmdtaglen);
21742198

21752199
set_ps_display_with_len(cmdtagname, cmdtaglen);

src/backend/utils/activity/backend_status.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ pgstat_bestart_initial(void)
321321
lbeentry.st_progress_command = PROGRESS_COMMAND_INVALID;
322322
lbeentry.st_progress_command_target = InvalidOid;
323323
lbeentry.st_query_id = UINT64CONST(0);
324+
lbeentry.st_plan_id = UINT64CONST(0);
324325

325326
/*
326327
* we don't zero st_progress_param here to save cycles; nobody should
@@ -599,6 +600,7 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
599600
/* st_xact_start_timestamp and wait_event_info are also disabled */
600601
beentry->st_xact_start_timestamp = 0;
601602
beentry->st_query_id = UINT64CONST(0);
603+
beentry->st_plan_id = UINT64CONST(0);
602604
proc->wait_event_info = 0;
603605
PGSTAT_END_WRITE_ACTIVITY(beentry);
604606
}
@@ -659,7 +661,10 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
659661
* identifier.
660662
*/
661663
if (state == STATE_RUNNING)
664+
{
662665
beentry->st_query_id = UINT64CONST(0);
666+
beentry->st_plan_id = UINT64CONST(0);
667+
}
663668

664669
if (cmd_str != NULL)
665670
{
@@ -710,6 +715,44 @@ pgstat_report_query_id(uint64 query_id, bool force)
710715
PGSTAT_END_WRITE_ACTIVITY(beentry);
711716
}
712717

718+
/* --------
719+
* pgstat_report_plan_id() -
720+
*
721+
* Called to update top-level plan identifier.
722+
* --------
723+
*/
724+
void
725+
pgstat_report_plan_id(uint64 plan_id, bool force)
726+
{
727+
volatile PgBackendStatus *beentry = MyBEEntry;
728+
729+
/*
730+
* if track_activities is disabled, st_plan_id should already have been
731+
* reset
732+
*/
733+
if (!beentry || !pgstat_track_activities)
734+
return;
735+
736+
/*
737+
* We only report the top-level plan identifiers. The stored plan_id is
738+
* reset when a backend calls pgstat_report_activity(STATE_RUNNING), or
739+
* with an explicit call to this function using the force flag. If the
740+
* saved plan identifier is not zero it means that it's not a top-level
741+
* command, so ignore the one provided unless it's an explicit call to
742+
* reset the identifier.
743+
*/
744+
if (beentry->st_plan_id != 0 && !force)
745+
return;
746+
747+
/*
748+
* Update my status entry, following the protocol of bumping
749+
* st_changecount before and after. We use a volatile pointer here to
750+
* ensure the compiler doesn't try to get cute.
751+
*/
752+
PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
753+
beentry->st_plan_id = plan_id;
754+
PGSTAT_END_WRITE_ACTIVITY(beentry);
755+
}
713756

714757
/* ----------
715758
* pgstat_report_appname() -
@@ -1106,6 +1149,21 @@ pgstat_get_my_query_id(void)
11061149
return MyBEEntry->st_query_id;
11071150
}
11081151

1152+
/* ----------
1153+
* pgstat_get_my_plan_id() -
1154+
*
1155+
* Return current backend's plan identifier.
1156+
*/
1157+
uint64
1158+
pgstat_get_my_plan_id(void)
1159+
{
1160+
if (!MyBEEntry)
1161+
return 0;
1162+
1163+
/* No need for a lock, for roughly the same reasons as above. */
1164+
return MyBEEntry->st_plan_id;
1165+
}
1166+
11091167
/* ----------
11101168
* pgstat_get_backend_type_by_proc_number() -
11111169
*

src/include/nodes/plannodes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ typedef struct PlannedStmt
5555
/* query identifier (copied from Query) */
5656
uint64 queryId;
5757

58+
/* plan identifier (can be set by plugins) */
59+
uint64 planId;
60+
5861
/* is it insert|update|delete|merge RETURNING? */
5962
bool hasReturning;
6063

src/include/utils/backend_status.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ typedef struct PgBackendStatus
171171

172172
/* query identifier, optionally computed using post_parse_analyze_hook */
173173
uint64 st_query_id;
174+
175+
/* plan identifier, optionally computed using planner_hook */
176+
uint64 st_plan_id;
174177
} PgBackendStatus;
175178

176179

@@ -319,13 +322,15 @@ extern void pgstat_clear_backend_activity_snapshot(void);
319322
/* Activity reporting functions */
320323
extern void pgstat_report_activity(BackendState state, const char *cmd_str);
321324
extern void pgstat_report_query_id(uint64 query_id, bool force);
325+
extern void pgstat_report_plan_id(uint64 plan_id, bool force);
322326
extern void pgstat_report_tempfile(size_t filesize);
323327
extern void pgstat_report_appname(const char *appname);
324328
extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
325329
extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
326330
extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
327331
int buflen);
328332
extern uint64 pgstat_get_my_query_id(void);
333+
extern uint64 pgstat_get_my_plan_id(void);
329334
extern BackendType pgstat_get_backend_type_by_proc_number(ProcNumber procNumber);
330335

331336

0 commit comments

Comments
 (0)