Re: pg_stat_statements and "IN" conditions

Sami Imseih <samimseih@gmail.com>

From: Sami Imseih <samimseih@gmail.com>
To: Dmitry Dolgov <9erthalion6@gmail.com>
Cc: Julien Rouhaud <rjuju123@gmail.com>, Álvaro Herrera <alvherre@alvh.no-ip.org>, Kirill Reshke <reshkekirill@gmail.com>, Sergei Kornilov <sk@zsrv.org>, yasuo.honda@gmail.com, tgl@sss.pgh.pa.us, smithpb2250@gmail.com, vignesh21@gmail.com, michael@paquier.xyz, nathandbossart@gmail.com, stark.cfm@gmail.com, geidav.pg@gmail.com, marcos@f10.com.br, robertmhaas@gmail.com, david@pgmasters.net, pgsql-hackers@postgresql.org, pavel.trukhanov@gmail.com, Sutou Kouhei <kou@clear-code.com>
Date: 2025-02-17T15:51:32Z
Lists: pgsql-hackers

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Introduce squashing of constant lists in query jumbling

  2. Make documentation builds reproducible

  3. Include values of A_Const nodes in query jumbling

  4. Teach planner about more monotonic window functions

  5. Split up guc.c for better build speed and ease of maintenance.

> This should do it. The last patch for today,

I looked at v27 today and have a few comments.

1/ It looks like the CTE test is missing a check for results.

"""
-- Test constants evaluation in a CTE, which was causing issues in the past
WITH cte AS (
SELECT 'const' as const FROM test_merge
)
SELECT ARRAY['a', 'b', 'c', const::varchar] AS result
FROM cte;

-- Simple array would be merged as well
SELECT pg_stat_statements_reset() IS NOT NULL AS t;
"""

2/ Looking at IsMergeableConst, I am not sure why we care about
things like function volatility, implicit cast or funcid > FirstGenbkiObjectId?

+               if (func->funcid > FirstGenbkiObjectId)
+                       return false;
+
+               if (func->funcformat != COERCE_IMPLICIT_CAST)
+                       return false;
+
+               if (!list_member_oid(*known_immutable_funcs, func->funcid))
+               {
+                       /* Not found in the cache, verify and add if needed */
+                       if(func_volatile(func->funcid) != PROVOLATILE_IMMUTABLE)
+                               return false;
+
+                       *known_immutable_funcs =
lappend_oid(*known_immutable_funcs,
+
                          func->funcid);
+               }

Shouldn't we just be looking for Constants (or PARAM_EXTERNAL) and if so
record the location, and for all other conditions, simply call _jumbleNode? Why
wouldn't that be enough?

3/ Here, this looks wrong as we could end up traversing an elements list
twice. Once inside IsMergeableConstList and if that call returns false, we end
up traversing through the elements list again in _jumbleNode.

+       Node *first, *last;
+       if (IsMergeableConstList(elements, &first, &last))
+       {
+               /*
+                * Both first and last constants have to be recorded.
The first one
+                * will indicate the merged interval, the last one
will tell us the
+                * length of the interval within the query text.
+                *
+                * Note that for the last expression we actually need
not the expression
+                * location (which is the leftmost expression), but
where it ends. For
+                * the limited set of supported cases now (implicit coerce via
+                * FuncExpr, Const) it's fine to use exprLocation, but
if more complex
+                * composite expressions will be supported, e.g.
OpExpr or FuncExpr as
+                * an explicit call, the rightmost expression will be needed.
+                */
+               RecordConstLocation(jstate, exprLocation(first), true);
+               RecordConstLocation(jstate, exprLocation(last), true);
+       }
+       else
+       {
+               _jumbleNode(jstate, (Node *) elements);
+       }
+}


Regards,

Sami