From ba90eac7a9953f6f6fa5e0a0cc7441d09778f8b9 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Wed, 25 Sep 2024 10:04:44 +0900 Subject: [PATCH] pg_stat_statements: Expand tests for SET statements There are many grammar flavors that depend on the parse node VariableSetStmt. This closes the gap in pg_stat_statements by providing test coverage for what should be a large majority of them, improving more the work begun in de2aca288569. This will be used to ease the evaluation of a path towards more normalization of SET queries with query jumbling. Note that SET NAMES (grammar from the standard, synonym of SET client_encoding) is omitted on purpose, this could use UTF8 with a conditional script where UTF8 is supported, but that does not seem worth the maintenance cost for the sake of these tests. The author has submitted most of these in a TAP test (filled in any holes I could spot), still queries in a SQL file of pg_stat_statements is able to achieve the same goal while being easier to look at when testing normalization patterns. Author: Greg Sabino Mullane, Michael Paquier Discussion: https://postgr.es/m/CAKAnmmJtJY2jzQN91=2QAD2eAJAA-Per61eyO48-TyxEg-q0Rg@mail.gmail.com --- .../pg_stat_statements/expected/utility.out | 95 +++++++++++++++++-- contrib/pg_stat_statements/sql/utility.sql | 47 ++++++++- 2 files changed, 132 insertions(+), 10 deletions(-) diff --git a/contrib/pg_stat_statements/expected/utility.out b/contrib/pg_stat_statements/expected/utility.out index fa738b5c00..8d3fd77201 100644 --- a/contrib/pg_stat_statements/expected/utility.out +++ b/contrib/pg_stat_statements/expected/utility.out @@ -66,7 +66,8 @@ DROP SERVER server_stats; DROP FOREIGN DATA WRAPPER wrapper_stats; -- Functions CREATE FUNCTION func_stats(a text DEFAULT 'a_data', b text DEFAULT lower('b_data')) - RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL; + RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL + SET work_mem = '256kB'; DROP FUNCTION func_stats; -- Rules CREATE TABLE tab_rule_stats (a int, b int); @@ -106,7 +107,8 @@ SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; 1 | 0 | CREATE FOREIGN DATA WRAPPER wrapper_stats 1 | 0 | CREATE FOREIGN TABLE foreign_stats (a int) SERVER server_stats 1 | 0 | CREATE FUNCTION func_stats(a text DEFAULT 'a_data', b text DEFAULT lower('b_data'))+ - | | RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL + | | RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL + + | | SET work_mem = '256kB' 1 | 0 | CREATE FUNCTION trigger_func_stats () RETURNS trigger LANGUAGE plpgsql + | | AS $$ BEGIN return OLD; end; $$ 1 | 0 | CREATE INDEX pt_stats2_index ON ONLY pt_stats2 (a) @@ -551,12 +553,26 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t; -- SET statements. -- These use two different strings, still they count as one entry. +CREATE ROLE regress_stat_set_1; +CREATE ROLE regress_stat_set_2; SET work_mem = '1MB'; Set work_mem = '1MB'; SET work_mem = '2MB'; +SET work_mem = DEFAULT; +SET work_mem TO DEFAULT; +SET work_mem FROM CURRENT; +BEGIN; +SET LOCAL work_mem = '128kB'; +SET LOCAL work_mem = '256kB'; +SET LOCAL work_mem = DEFAULT; +SET LOCAL work_mem TO DEFAULT; +SET LOCAL work_mem FROM CURRENT; +COMMIT; RESET work_mem; SET enable_seqscan = off; SET enable_seqscan = on; +SET SESSION work_mem = '300kB'; +SET SESSION work_mem = '400kB'; RESET enable_seqscan; -- SET TRANSACTION ISOLATION BEGIN; @@ -564,33 +580,77 @@ SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; COMMIT; --- SET SESSION CHARACTERISTICS +-- SET SESSION AUTHORIZATION SET SESSION SESSION AUTHORIZATION DEFAULT; +SET SESSION AUTHORIZATION 'regress_stat_set_1'; +SET SESSION AUTHORIZATION 'regress_stat_set_2'; RESET SESSION AUTHORIZATION; BEGIN; SET LOCAL SESSION AUTHORIZATION DEFAULT; +SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_1'; +SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_2'; RESET SESSION AUTHORIZATION; COMMIT; +-- SET SESSION CHARACTERISTICS +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY; +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ ONLY; +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ WRITE; +-- SET XML OPTION +SET XML OPTION DOCUMENT; +SET XML OPTION CONTENT; +-- SET TIME ZONE +SET TIME ZONE 'America/New_York'; +SET TIME ZONE 'Asia/Tokyo'; +SET TIME ZONE DEFAULT; +SET TIME ZONE LOCAL; +SET TIME ZONE 'CST7CDT,M4.1.0,M10.5.0'; +RESET TIME ZONE; SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; - calls | rows | query --------+------+---------------------------------------------------- - 2 | 0 | BEGIN - 2 | 0 | COMMIT + calls | rows | query +-------+------+------------------------------------------------------------------ + 3 | 0 | BEGIN + 3 | 0 | COMMIT + 1 | 0 | CREATE ROLE regress_stat_set_1 + 1 | 0 | CREATE ROLE regress_stat_set_2 2 | 0 | RESET SESSION AUTHORIZATION + 1 | 0 | RESET TIME ZONE 1 | 0 | RESET enable_seqscan 1 | 0 | RESET work_mem 1 | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t + 1 | 0 | SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_1' + 1 | 0 | SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_2' 1 | 0 | SET LOCAL SESSION AUTHORIZATION DEFAULT + 1 | 0 | SET LOCAL work_mem = '128kB' + 1 | 0 | SET LOCAL work_mem = '256kB' + 2 | 0 | SET LOCAL work_mem = DEFAULT + 1 | 0 | SET LOCAL work_mem FROM CURRENT + 1 | 0 | SET SESSION AUTHORIZATION 'regress_stat_set_1' + 1 | 0 | SET SESSION AUTHORIZATION 'regress_stat_set_2' + 1 | 0 | SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY + 1 | 0 | SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ ONLY + 1 | 0 | SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ WRITE 1 | 0 | SET SESSION SESSION AUTHORIZATION DEFAULT + 1 | 0 | SET SESSION work_mem = '300kB' + 1 | 0 | SET SESSION work_mem = '400kB' + 1 | 0 | SET TIME ZONE 'America/New_York' + 1 | 0 | SET TIME ZONE 'Asia/Tokyo' + 1 | 0 | SET TIME ZONE 'CST7CDT,M4.1.0,M10.5.0' + 2 | 0 | SET TIME ZONE DEFAULT 1 | 0 | SET TRANSACTION ISOLATION LEVEL READ COMMITTED 1 | 0 | SET TRANSACTION ISOLATION LEVEL REPEATABLE READ 1 | 0 | SET TRANSACTION ISOLATION LEVEL SERIALIZABLE + 1 | 0 | SET XML OPTION CONTENT + 1 | 0 | SET XML OPTION DOCUMENT 1 | 0 | SET enable_seqscan = off 1 | 0 | SET enable_seqscan = on 2 | 0 | SET work_mem = '1MB' 1 | 0 | SET work_mem = '2MB' -(15 rows) + 2 | 0 | SET work_mem = DEFAULT + 1 | 0 | SET work_mem FROM CURRENT +(39 rows) +DROP ROLE regress_stat_set_1; +DROP ROLE regress_stat_set_2; SELECT pg_stat_statements_reset() IS NOT NULL AS t; t --- @@ -664,3 +724,22 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t; t (1 row) +-- Special cases. Keep these ones at the end to avoid conflicts. +SET SCHEMA 'foo'; +SET SCHEMA 'public'; +RESET ALL; +SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | rows | query +-------+------+---------------------------------------------------- + 1 | 0 | RESET ALL + 1 | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t + 1 | 0 | SET SCHEMA 'foo' + 1 | 0 | SET SCHEMA 'public' +(4 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + diff --git a/contrib/pg_stat_statements/sql/utility.sql b/contrib/pg_stat_statements/sql/utility.sql index 4f7afece1d..dd97203c21 100644 --- a/contrib/pg_stat_statements/sql/utility.sql +++ b/contrib/pg_stat_statements/sql/utility.sql @@ -47,7 +47,8 @@ DROP FOREIGN DATA WRAPPER wrapper_stats; -- Functions CREATE FUNCTION func_stats(a text DEFAULT 'a_data', b text DEFAULT lower('b_data')) - RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL; + RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL + SET work_mem = '256kB'; DROP FUNCTION func_stats; -- Rules @@ -277,12 +278,26 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t; -- SET statements. -- These use two different strings, still they count as one entry. +CREATE ROLE regress_stat_set_1; +CREATE ROLE regress_stat_set_2; SET work_mem = '1MB'; Set work_mem = '1MB'; SET work_mem = '2MB'; +SET work_mem = DEFAULT; +SET work_mem TO DEFAULT; +SET work_mem FROM CURRENT; +BEGIN; +SET LOCAL work_mem = '128kB'; +SET LOCAL work_mem = '256kB'; +SET LOCAL work_mem = DEFAULT; +SET LOCAL work_mem TO DEFAULT; +SET LOCAL work_mem FROM CURRENT; +COMMIT; RESET work_mem; SET enable_seqscan = off; SET enable_seqscan = on; +SET SESSION work_mem = '300kB'; +SET SESSION work_mem = '400kB'; RESET enable_seqscan; -- SET TRANSACTION ISOLATION BEGIN; @@ -290,15 +305,35 @@ SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; COMMIT; --- SET SESSION CHARACTERISTICS +-- SET SESSION AUTHORIZATION SET SESSION SESSION AUTHORIZATION DEFAULT; +SET SESSION AUTHORIZATION 'regress_stat_set_1'; +SET SESSION AUTHORIZATION 'regress_stat_set_2'; RESET SESSION AUTHORIZATION; BEGIN; SET LOCAL SESSION AUTHORIZATION DEFAULT; +SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_1'; +SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_2'; RESET SESSION AUTHORIZATION; COMMIT; +-- SET SESSION CHARACTERISTICS +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY; +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ ONLY; +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ WRITE; +-- SET XML OPTION +SET XML OPTION DOCUMENT; +SET XML OPTION CONTENT; +-- SET TIME ZONE +SET TIME ZONE 'America/New_York'; +SET TIME ZONE 'Asia/Tokyo'; +SET TIME ZONE DEFAULT; +SET TIME ZONE LOCAL; +SET TIME ZONE 'CST7CDT,M4.1.0,M10.5.0'; +RESET TIME ZONE; SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; +DROP ROLE regress_stat_set_1; +DROP ROLE regress_stat_set_2; SELECT pg_stat_statements_reset() IS NOT NULL AS t; -- @@ -329,3 +364,11 @@ DROP TABLE pgss_ctas; DROP TABLE pgss_select_into; SELECT pg_stat_statements_reset() IS NOT NULL AS t; + +-- Special cases. Keep these ones at the end to avoid conflicts. +SET SCHEMA 'foo'; +SET SCHEMA 'public'; +RESET ALL; +SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + +SELECT pg_stat_statements_reset() IS NOT NULL AS t;