On Mon, Jun 09, 2025 at 12:44:59PM +0200, Alvaro Herrera wrote: > I also added a recursive call in IsSquashableExpression to itself. The > check for stack depth can be done without throwing an error. I tested > this by adding stack bloat in that function. I also renamed it to > IsSquashableConstant. This changes one of the tests, because a cast > sequence like 42::int::bigint::int is considered squashable. > > Other than that, the changes are cosmetic. > > Barring objections, I'll push this soon, then look at rebasing 0003 on > top, which I expect to be an easy job.
v9-0002 is failing in the CI for the freebsd task: https://github.com/michaelpq/postgres/runs/43784034162 Here is the link to the diffs, also attached to this message: https://api.cirrus-ci.com/v1/artifact/task/5378459897167872/testrun/build/testrun/pg_stat_statements/regress/regression.diffs I am also able to reproduce these failures locally, FWIW. For example, with a IN clause made of integer constants gets converted to an ArrayExpr, but in _jumbleElements() we fail to call RecordConstLocation() and the list is not squashed. I think that this is can be reproduced by -DWRITE_READ_PARSE_PLAN_TREES -DCOPY_PARSE_PLAN_TREES -DRAW_EXPRESSION_COVERAGE_TEST that I always include in my builds. The freebsd task uses the same with debug_copy_parse_plan_trees=on, debug_write_read_parse_plan_trees=on and debug_raw_expression_coverage_test=on. -- Michael
diff -U3 /tmp/cirrus-ci-build/contrib/pg_stat_statements/expected/select.out
/tmp/cirrus-ci-build/build/testrun/pg_stat_statements/regress/results/select.out
--- /tmp/cirrus-ci-build/contrib/pg_stat_statements/expected/select.out
2025-06-10 06:13:14.867518000 +0000
+++
/tmp/cirrus-ci-build/build/testrun/pg_stat_statements/regress/results/select.out
2025-06-10 06:16:54.005179000 +0000
@@ -292,10 +292,11 @@
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
query |
calls
------------------------------------------------------------------------+-------
- SELECT WHERE $1 IN ($2 /*, ... */) | 2
+ SELECT WHERE $1 = ANY (ARRAY[$2 /*, ... */]) | 1
+ SELECT WHERE $1 IN ($2, int4($3), int4($4)) | 1
SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C" | 0
-(3 rows)
+(4 rows)
--
-- queries with locking clauses
diff -U3 /tmp/cirrus-ci-build/contrib/pg_stat_statements/expected/dml.out
/tmp/cirrus-ci-build/build/testrun/pg_stat_statements/regress/results/dml.out
--- /tmp/cirrus-ci-build/contrib/pg_stat_statements/expected/dml.out
2025-06-10 06:13:14.866052000 +0000
+++
/tmp/cirrus-ci-build/build/testrun/pg_stat_statements/regress/results/dml.out
2025-06-10 06:16:54.106500000 +0000
@@ -80,7 +80,7 @@
1 | 10 | INSERT INTO pgss_dml_tab VALUES(generate_series($1, $2), $3)
1 | 12 | SELECT * FROM pgss_dml_tab ORDER BY a
2 | 4 | SELECT * FROM pgss_dml_tab WHERE a > $1 ORDER BY a
- 1 | 8 | SELECT * FROM pgss_dml_tab WHERE a IN ($1 /*, ... */)
+ 1 | 8 | SELECT * FROM pgss_dml_tab WHERE a IN ($1, $2, $3, $4, $5)
1 | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t
1 | 0 | SET pg_stat_statements.track_utility = $1
6 | 6 | UPDATE pgss_dml_tab SET b = $1 WHERE a = $2
diff -U3 /tmp/cirrus-ci-build/contrib/pg_stat_statements/expected/squashing.out
/tmp/cirrus-ci-build/build/testrun/pg_stat_statements/regress/results/squashing.out
--- /tmp/cirrus-ci-build/contrib/pg_stat_statements/expected/squashing.out
2025-06-10 06:13:14.867938000 +0000
+++
/tmp/cirrus-ci-build/build/testrun/pg_stat_statements/regress/results/squashing.out
2025-06-10 06:17:00.844056000 +0000
@@ -73,12 +73,14 @@
(1 row)
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
- query | calls
--------------------------------------------------------+-------
- SELECT * FROM test_squash WHERE id IN ($1 /*, ... */) | 3
- SELECT ARRAY[$1 /*, ... */] | 3
- SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
-(3 rows)
+ query | calls
+------------------------------------------------------------+-------
+ SELECT * FROM test_squash WHERE id IN ($1, $2, $3) | 1
+ SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4) | 1
+ SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5) | 1
+ SELECT ARRAY[$1 /*, ... */] | 3
+ SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
+(5 rows)
-- built-in functions will be squashed
-- the IN and ARRAY forms of this statement will have the same queryId
@@ -99,9 +101,10 @@
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
query | calls
----------------------------------------------------+-------
- SELECT WHERE $1 IN ($2 /*, ... */) | 2
+ SELECT WHERE $1 = ANY (ARRAY[$2 /*, ... */]) | 1
+ SELECT WHERE $1 IN ($2, int4($3), int4($4), $5) | 1
SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
-(2 rows)
+(3 rows)
-- external parameters will not be squashed
SELECT pg_stat_statements_reset() IS NOT NULL AS t;
@@ -200,11 +203,14 @@
(0 rows)
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
- query | calls
----------------------------------------------------------------------+-------
- SELECT * FROM test_squash WHERE id IN ($1 /*, ... */) AND data = $2 | 6
- SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
-(2 rows)
+ query
| calls
+-----------------------------------------------------------------------------------------------------+-------
+ SELECT * FROM test_squash WHERE id = ANY (ARRAY[$1 /*, ... */]) AND data = $2
| 3
+ SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5, $6, $7, $8, $9)
AND data = $10 | 1
+ SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5, $6, $7, $8, $9,
$10) AND data = $11 | 1
+ SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5, $6, $7, $8, $9,
$10, $11) AND data = $12 | 1
+ SELECT pg_stat_statements_reset() IS NOT NULL AS t
| 1
+(5 rows)
-- Multiple squashed intervals
SELECT pg_stat_statements_reset() IS NOT NULL AS t;
@@ -250,12 +256,18 @@
(0 rows)
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
- query | calls
--------------------------------------------------------+-------
- SELECT * FROM test_squash WHERE id IN ($1 /*, ... */)+| 6
- AND data IN ($2 /*, ... */) |
- SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
-(2 rows)
+ query
| calls
+--------------------------------------------------------------------------------------+-------
+ SELECT * FROM test_squash WHERE id = ANY (ARRAY[$1 /*, ... */])
+| 3
+ AND data = ANY (ARRAY[$2 /*, ... */])
|
+ SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5, $6, $7, $8, $9)
+| 1
+ AND data IN ($10, $11, $12, $13, $14, $15, $16, $17, $18)
|
+ SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5, $6, $7, $8, $9,
$10) +| 1
+ AND data IN ($11, $12, $13, $14, $15, $16, $17, $18, $19, $20)
|
+ SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5, $6, $7, $8, $9,
$10, $11)+| 1
+ AND data IN ($12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22)
|
+ SELECT pg_stat_statements_reset() IS NOT NULL AS t
| 1
+(5 rows)
SELECT pg_stat_statements_reset() IS NOT NULL AS t;
t
@@ -372,9 +384,14 @@
query | calls
--------------------------------------------------------------------+-------
SELECT data FROM test_float WHERE data = ANY(ARRAY[$1 /*, ... */]) | 3
- SELECT data FROM test_float WHERE data IN ($1 /*, ... */) | 7
+ SELECT data FROM test_float WHERE data = ANY(ARRAY[$1 /*, ... */]) | 2
+ SELECT data FROM test_float WHERE data IN ($1, $2) | 1
+ SELECT data FROM test_float WHERE data IN ($1, $2) | 1
+ SELECT data FROM test_float WHERE data IN ($1, $2) | 1
+ SELECT data FROM test_float WHERE data IN ($1, $2) | 1
+ SELECT data FROM test_float WHERE data IN ($1, $2) | 1
SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
-(3 rows)
+(8 rows)
-- Numeric type, implicit cast is squashed
CREATE TABLE test_squash_numeric (id int, data numeric(5, 2));
@@ -395,11 +412,11 @@
(0 rows)
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
- query |
calls
---------------------------------------------------------------------------+-------
- SELECT * FROM test_squash_numeric WHERE data = ANY(ARRAY[$1 /*, ... */]) |
1
- SELECT * FROM test_squash_numeric WHERE data IN ($1 /*, ... */) |
1
- SELECT pg_stat_statements_reset() IS NOT NULL AS t |
1
+ query
| calls
+------------------------------------------------------------------------------------------------+-------
+ SELECT * FROM test_squash_numeric WHERE data = ANY(ARRAY[$1 /*, ... */])
| 1
+ SELECT * FROM test_squash_numeric WHERE data IN ($1, $2, $3, $4, $5, $6, $7,
$8, $9, $10, $11) | 1
+ SELECT pg_stat_statements_reset() IS NOT NULL AS t
| 1
(3 rows)
-- Bigint, implicit cast is squashed
@@ -421,11 +438,11 @@
(0 rows)
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
- query |
calls
--------------------------------------------------------------------------+-------
- SELECT * FROM test_squash_bigint WHERE data = ANY(ARRAY[$1 /*, ... */]) |
1
- SELECT * FROM test_squash_bigint WHERE data IN ($1 /*, ... */) |
1
- SELECT pg_stat_statements_reset() IS NOT NULL AS t |
1
+ query
| calls
+-----------------------------------------------------------------------------------------------+-------
+ SELECT * FROM test_squash_bigint WHERE data = ANY(ARRAY[$1 /*, ... */])
| 1
+ SELECT * FROM test_squash_bigint WHERE data IN ($1, $2, $3, $4, $5, $6, $7,
$8, $9, $10, $11) | 1
+ SELECT pg_stat_statements_reset() IS NOT NULL AS t
| 1
(3 rows)
-- Bigint, explicit cast is squashed
@@ -450,12 +467,14 @@
(0 rows)
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
- query | calls
-----------------------------------------------------+-------
- SELECT * FROM test_squash_bigint WHERE data IN +| 2
- ($1 /*, ... */) |
- SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
-(2 rows)
+ query
| calls
+----------------------------------------------------------------------------------+-------
+ SELECT * FROM test_squash_bigint WHERE data = ANY(ARRAY[$1 /*, ... */])
| 1
+ SELECT * FROM test_squash_bigint WHERE data IN
+| 1
+ ($1::bigint, $2::bigint, $3::bigint, $4::bigint, $5::bigint,
$6::bigint,+|
+ $7::bigint, $8::bigint, $9::bigint, $10::bigint, $11::bigint)
|
+ SELECT pg_stat_statements_reset() IS NOT NULL AS t
| 1
+(3 rows)
-- Bigint, long tokens with parenthesis, will not squash
SELECT pg_stat_statements_reset() IS NOT NULL AS t;
@@ -503,11 +522,12 @@
(1 row)
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
- query | calls
-----------------------------------------------------+-------
- SELECT WHERE $1 IN ($2 /*, ... */) | 2
- SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
-(2 rows)
+ query | calls
+-----------------------------------------------------------------+-------
+ SELECT WHERE $1 = ANY(ARRAY[$2 /*, ... */]) | 1
+ SELECT WHERE $1 IN ($2::int::bigint::int, $3::int::bigint::int) | 1
+ SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
+(3 rows)
--
-- CoerceViaIO
@@ -569,12 +589,17 @@
(0 rows)
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
- query | calls
-----------------------------------------------------+-------
- SELECT * FROM test_squash_cast WHERE data IN +| 2
- ($1 /*, ... */) |
- SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
-(2 rows)
+ query
| calls
+----------------------------------------------------------------------------------+-------
+ SELECT * FROM test_squash_cast WHERE data = ANY (ARRAY
+| 1
+ [$1 /*, ... */])
|
+ SELECT * FROM test_squash_cast WHERE data IN
+| 1
+ ($1::int4::casttesttype, $2::int4::casttesttype,
$3::int4::casttesttype,+|
+ $4::int4::casttesttype, $5::int4::casttesttype,
$6::int4::casttesttype,+|
+ $7::int4::casttesttype, $8::int4::casttesttype,
$9::int4::casttesttype,+|
+ $10::int4::casttesttype, $11::int4::casttesttype)
|
+ SELECT pg_stat_statements_reset() IS NOT NULL AS t
| 1
+(3 rows)
-- Some casting expression are simplified to Const
CREATE TABLE test_squash_jsonb (id int, data jsonb);
@@ -601,12 +626,16 @@
(0 rows)
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
- query | calls
-----------------------------------------------------+-------
- SELECT * FROM test_squash_jsonb WHERE data IN +| 2
- ($1 /*, ... */) |
- SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
-(2 rows)
+ query | calls
+--------------------------------------------------------------+-------
+ SELECT * FROM test_squash_jsonb WHERE data = ANY (ARRAY +| 1
+ [$1 /*, ... */]) |
+ SELECT * FROM test_squash_jsonb WHERE data IN +| 1
+ (($1)::jsonb, ($2)::jsonb, ($3)::jsonb, ($4)::jsonb,+|
+ ($5)::jsonb, ($6)::jsonb, ($7)::jsonb, ($8)::jsonb,+|
+ ($9)::jsonb, ($10)::jsonb) |
+ SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
+(3 rows)
-- CoerceViaIO, SubLink instead of a Const. Will not squash
SELECT pg_stat_statements_reset() IS NOT NULL AS t;
@@ -701,13 +730,13 @@
(0 rows)
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
- query | calls
---------------------------------------------------------------------+-------
- SELECT * FROM test_squash WHERE id IN +| 1
- ($1 /*, ... */) |
- SELECT * FROM test_squash WHERE id IN ($1::oid, $2::oid::int::oid) | 2
- SELECT ARRAY[$1 /*, ... */] | 1
- SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
+ query
| calls
+-------------------------------------------------------------------------------------------+-------
+ SELECT * FROM test_squash WHERE id IN
+| 1
+ ($1::oid, $2::oid, $3::oid, $4::oid, $5::oid, $6::oid, $7::oid,
$8::oid, $9::oid) |
+ SELECT * FROM test_squash WHERE id IN ($1::oid, $2::oid::int::oid)
| 2
+ SELECT ARRAY[$1 /*, ... */]
| 1
+ SELECT pg_stat_statements_reset() IS NOT NULL AS t
| 1
(4 rows)
--
@@ -773,7 +802,7 @@
query | calls
----------------------------------------------------+-------
SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
- select where $1 IN ($2 /*, ... */) | 1
+ select where $1 IN ($2::int, $3::int) | 1
select where $1 IN ($2::int, $3::int::text) | 1
(3 rows)
@@ -797,8 +826,9 @@
query | calls
----------------------------------------------------+-------
SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
- select where $1 IN ($2 /*, ... */) | 2
-(2 rows)
+ select where $1 = ANY (array[$2 /*, ... */]) | 1
+ select where $1 IN ($2::int::text, $3::int::text) | 1
+(3 rows)
--
-- cleanup
signature.asc
Description: PGP signature
