Re: Set query_id for query contained in utility statement

jian he <jian.universality@gmail.com>

From: jian he <jian.universality@gmail.com>
To: Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com>
Cc: Michael Paquier <michael@paquier.xyz>, PostgreSQL Hackers <pgsql-hackers@postgresql.org>
Date: 2024-10-04T12:16:00Z
Lists: pgsql-hackers
On Fri, Oct 4, 2024 at 5:05 PM Anthonin Bonnefoy
<anthonin.bonnefoy@datadoghq.com> wrote:
>
> I agree that tracking 2 identical statements with different queryIds
> and nesting levels is very confusing. On the other hand, from an
> extension developer point of view (not necessarily limited to
> pg_stat_statements), I would like to have the queryId available and
> the post_parse hook called so the query can be normalised and tracked
> in a hashmap.
>
> However, the repeated statements did bug me a lot so I took a stab at
> trying to find a possible solution. I made an attempt in 0001 by
> tracking the statements' locations of explainable statements (Select,
> Insert, Update, Merge, Delete...) during parse and propagate them in
> the generated Query during transform. With the change, we now have the
> following result:
>
> SET pg_stat_statements.track = 'all';
> explain (costs off) select 1;
> select 1;
> select queryid, calls, query, toplevel from pg_stat_statements
>      where query ~'select \$1';
>        queryid       | calls |             query             | toplevel
> ---------------------+-------+-------------------------------+----------
>  2800308901962295548 |     1 | select $1                     | t
>  2800308901962295548 |     1 | select $1;                    | f
>  3797185112479763582 |     1 | explain (costs off) select $1 | t
>
> The top level and nested select statement now share both the same
> queryId and query string. The additional ';' for the nested query is
> due to not having the statement length  and taking the whole
> statement.
>

about v5 0001
select_with_parens:
            '(' select_no_parens ')'                { $$ = $2; }
            | '(' select_with_parens ')'            { $$ = $2; }
        ;


 toplevel | calls |                         query
----------+-------+-------------------------------------------------------
 t        |     1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t
 t        |     0 | SELECT toplevel, calls, query FROM pg_stat_statements+
          |       |   ORDER BY query COLLATE "C", toplevel
 t        |     1 | explain (select $1)
 f        |     1 | select $1);

query "select $1);" looks weird. not sure how to improve it,
or this should be the expected behavior?



in gram.y
            | values_clause                            { $$ = $1; }
            | TABLE relation_expr
for TABLE relation_expr
we can add `n->location = @1;`

for values_clause we can do also,
then in transformValuesClause do the same as in transformSelectStmt.



Commits

  1. Set query ID for inner queries of CREATE TABLE AS and DECLARE

  2. Track more precisely query locations for nested statements

  3. pg_stat_statements: Add tests for nested queries with level tracking

  4. Fix race condition in COMMIT PREPARED causing orphaned 2PC files