postgres.git / summary / log / commit / refs

commit    21aad4bea86d7fc139eefaa55b92da9ba5f0dd5e
Author:   Michael Paquier <michael@paquier.xyz>
Date:     Wed Sep 18 00:59:19 2024 +0000
First released in: 18.0, 14.14, 15.9, 16.5, 17.0

    Add missing query ID reporting in extended query protocol
    
    This commit adds query ID reports for two code paths when processing
    extended query protocol messages:
    - When receiving a bind message, setting it to the first Query retrieved
    from a cached cache.
    - When receiving an execute message, setting it to the first PlannedStmt
    stored in a portal.
    
    An advantage of this method is that this is able to cover all the types
    of portals handled in the extended query protocol, particularly these
    two when the report done in ExecutorStart() is not enough (neither is an
    addition in ExecutorRun(), actually, for the second point):
    - Multiple execute messages, with multiple ExecutorRun().
    - Portal with execute/fetch messages, like a query with a RETURNING
    clause and a fetch size that stores the tuples in a first execute
    message going though ExecutorStart() and ExecuteRun(), followed by one
    or more execute messages doing only fetches from the tuplestore created
    in the first message.  This corresponds to the case where
    execute_is_fetch is set, for example.
    
    Note that the query ID reporting done in ExecutorStart() is still
    necessary, as an EXECUTE requires it.  Query ID reporting is optimistic
    and more calls to pgstat_report_query_id() don't matter as the first
    report takes priority except if the report is forced.  The comment in
    ExecutorStart() is adjusted to reflect better the reality with the
    extended query protocol.
    
    The test added in pg_stat_statements is a courtesy of Robert Haas.  This
    uses psql's \bind metacommand, hence this part is backpatched down to
    v16.
    
    Reported-by:  Kaido Vaikla, Erik Wienhold
    Author: Sami Imseih
    Reviewed-by: Jian He, Andrei Lepikhov, Michael Paquier
    Discussion: https://postgr.es/m/CA+427g8DiW3aZ6pOpVgkPbqK97ouBdf18VLiHFesea2jUk3XoQ@mail.gmail.com
    Discussion: https://postgr.es/m/CA+TgmoZxtnf_jZ=VqBSyaU8hfUkkwoJCJ6ufy4LGpXaunKrjrg@mail.gmail.com
    Discussion: https://postgr.es/m/1391613709.939460.1684777418070@office.mailbox.org
    Backpatch-through: 14


contrib/pg_stat_statements/Makefile | 2 +- contrib/pg_stat_statements/expected/extended.out | 10 ++++++++++ contrib/pg_stat_statements/meson.build | 1 + contrib/pg_stat_statements/sql/extended.sql | 7 +++++++ src/backend/executor/execMain.c | 10 ++++++---- src/backend/tcop/postgres.c | 24 ++++++++++++++++++++++++ 6 files changed, 49 insertions(+), 5 deletions(-) diff --git a/contrib/pg_stat_statements/Makefile b/contrib/pg_stat_statements/Makefile index 5578a9dd4e3..31e4fdeeb96 100644 --- a/contrib/pg_stat_statements/Makefile +++ b/contrib/pg_stat_statements/Makefile @@ -18,7 +18,7 @@ LDFLAGS_SL += $(filter -lm, $(LIBS)) REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/pg_stat_statements/pg_stat_statements.conf REGRESS = select dml cursors utility level_tracking planning \ - user_activity wal cleanup oldextversions + user_activity wal extended cleanup oldextversions # Disabled because these tests require "shared_preload_libraries=pg_stat_statements", # which typical installcheck users do not have (e.g. buildfarm clients). NO_INSTALLCHECK = 1 diff --git a/contrib/pg_stat_statements/expected/extended.out b/contrib/pg_stat_statements/expected/extended.out new file mode 100644 index 00000000000..dbc78680226 --- /dev/null +++ b/contrib/pg_stat_statements/expected/extended.out @@ -0,0 +1,10 @@ +-- Tests with extended query protocol +SET pg_stat_statements.track_utility = FALSE; +-- This test checks that an execute message sets a query ID. +SELECT query_id IS NOT NULL AS query_id_set + FROM pg_stat_activity WHERE pid = pg_backend_pid() \bind \g + query_id_set +-------------- + t +(1 row) + diff --git a/contrib/pg_stat_statements/meson.build b/contrib/pg_stat_statements/meson.build index 3e3062ada9c..d1a02c3e8fe 100644 --- a/contrib/pg_stat_statements/meson.build +++ b/contrib/pg_stat_statements/meson.build @@ -48,6 +48,7 @@ tests += { 'planning', 'user_activity', 'wal', + 'extended', 'cleanup', 'oldextversions', ], diff --git a/contrib/pg_stat_statements/sql/extended.sql b/contrib/pg_stat_statements/sql/extended.sql new file mode 100644 index 00000000000..07b6c5a93d6 --- /dev/null +++ b/contrib/pg_stat_statements/sql/extended.sql @@ -0,0 +1,7 @@ +-- Tests with extended query protocol + +SET pg_stat_statements.track_utility = FALSE; + +-- This test checks that an execute message sets a query ID. +SELECT query_id IS NOT NULL AS query_id_set + FROM pg_stat_activity WHERE pid = pg_backend_pid() \bind \g diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 4c5a7bbf620..fddcd086e68 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -132,10 +132,12 @@ void ExecutorStart(QueryDesc *queryDesc, int eflags) { /* - * In some cases (e.g. an EXECUTE statement) a query execution will skip - * parse analysis, which means that the query_id won't be reported. Note - * that it's harmless to report the query_id multiple times, as the call - * will be ignored if the top level query_id has already been reported. + * In some cases (e.g. an EXECUTE statement or an execute message with the + * extended query protocol) the query_id won't be reported, so do it now. + * + * Note that it's harmless to report the query_id multiple times, as the + * call will be ignored if the top level query_id has already been + * reported. */ pgstat_report_query_id(queryDesc->plannedstmt->queryId, false); diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index e7d486ca2fc..3f427f1b47f 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -1648,6 +1648,7 @@ exec_bind_message(StringInfo input_message) char msec_str[32]; ParamsErrorCbData params_data; ErrorContextCallback params_errcxt; + ListCell *lc; /* Get the fixed part of the message */ portal_name = pq_getmsgstring(input_message); @@ -1683,6 +1684,17 @@ exec_bind_message(StringInfo input_message) pgstat_report_activity(STATE_RUNNING, psrc->query_string); + foreach(lc, psrc->query_list) + { + Query *query = lfirst_node(Query, lc); + + if (query->queryId != UINT64CONST(0)) + { + pgstat_report_query_id(query->queryId, false); + break; + } + } + set_ps_display("BIND"); if (save_log_statement_stats) @@ -2109,6 +2121,7 @@ exec_execute_message(const char *portal_name, long max_rows) ErrorContextCallback params_errcxt; const char *cmdtagname; size_t cmdtaglen; + ListCell *lc; /* Adjust destination to tell printtup.c what to do */ dest = whereToSendOutput; @@ -2155,6 +2168,17 @@ exec_execute_message(const char *portal_name, long max_rows) pgstat_report_activity(STATE_RUNNING, sourceText); + foreach(lc, portal->stmts) + { + PlannedStmt *stmt = lfirst_node(PlannedStmt, lc); + + if (stmt->queryId != UINT64CONST(0)) + { + pgstat_report_query_id(stmt->queryId, false); + break; + } + } + cmdtagname = GetCommandTagNameAndLen(portal->commandTag, &cmdtaglen); set_ps_display_with_len(cmdtagname, cmdtaglen); [parent: b8b175a4c895]