-- -- Statement level tracking -- SELECT setting::integer < 140000 AS skip_test FROM pg_settings where name = 'server_version_num' \gset \if :skip_test \quit \endif CREATE EXTENSION pg_stat_monitor; SET pg_stat_monitor.pgsm_track_utility = TRUE; SET pg_stat_monitor.pgsm_normalized_query = TRUE; SELECT pg_stat_monitor_reset(); pg_stat_monitor_reset ----------------------- (1 row) -- DO block - top-level tracking. CREATE TABLE stats_track_tab (x int); SET pg_stat_monitor.pgsm_track = 'top'; DELETE FROM stats_track_tab; DO $$ BEGIN DELETE FROM stats_track_tab; END; $$ LANGUAGE plpgsql; SELECT toplevel, calls, query FROM pg_stat_monitor WHERE query LIKE '%DELETE%' ORDER BY query COLLATE "C", toplevel; toplevel | calls | query ----------+-------+-------------------------------- t | 1 | DELETE FROM stats_track_tab t | 1 | DO $$ + | | BEGIN + | | DELETE FROM stats_track_tab;+ | | END; + | | $$ LANGUAGE plpgsql (2 rows) SELECT pg_stat_monitor_reset(); pg_stat_monitor_reset ----------------------- (1 row) -- DO block - all-level tracking. SET pg_stat_monitor.pgsm_track = 'all'; DELETE FROM stats_track_tab; DO $$ BEGIN DELETE FROM stats_track_tab; END; $$; DO LANGUAGE plpgsql $$ BEGIN -- this is a SELECT PERFORM 'hello world'::TEXT; END; $$; SELECT toplevel, calls, query FROM pg_stat_monitor ORDER BY query COLLATE "C", toplevel; toplevel | calls | query ----------+-------+---------------------------------------- f | 1 | DELETE FROM stats_track_tab t | 1 | DELETE FROM stats_track_tab t | 1 | DO $$ + | | BEGIN + | | DELETE FROM stats_track_tab; + | | END; $$ t | 1 | DO LANGUAGE plpgsql $$ + | | BEGIN + | | -- this is a SELECT + | | PERFORM 'hello world'::TEXT; + | | END; $$ f | 1 | SELECT $1::TEXT t | 1 | SELECT pg_stat_monitor_reset() t | 1 | SET pg_stat_monitor.pgsm_track = 'all' (7 rows) -- DO block - top-level tracking without utility. SET pg_stat_monitor.pgsm_track = 'top'; SET pg_stat_monitor.pgsm_track_utility = FALSE; SELECT pg_stat_monitor_reset(); pg_stat_monitor_reset ----------------------- (1 row) DELETE FROM stats_track_tab; DO $$ BEGIN DELETE FROM stats_track_tab; END; $$; DO LANGUAGE plpgsql $$ BEGIN -- this is a SELECT PERFORM 'hello world'::TEXT; END; $$; SELECT toplevel, calls, query FROM pg_stat_monitor ORDER BY query COLLATE "C", toplevel; toplevel | calls | query ----------+-------+-------------------------------- t | 1 | DELETE FROM stats_track_tab t | 1 | SELECT pg_stat_monitor_reset() (2 rows) -- DO block - all-level tracking without utility. SET pg_stat_monitor.pgsm_track = 'all'; SELECT pg_stat_monitor_reset(); pg_stat_monitor_reset ----------------------- (1 row) DELETE FROM stats_track_tab; DO $$ BEGIN DELETE FROM stats_track_tab; END; $$; DO LANGUAGE plpgsql $$ BEGIN -- this is a SELECT PERFORM 'hello world'::TEXT; END; $$; SELECT toplevel, calls, query FROM pg_stat_monitor ORDER BY query COLLATE "C", toplevel; toplevel | calls | query ----------+-------+-------------------------------- f | 1 | DELETE FROM stats_track_tab t | 1 | DELETE FROM stats_track_tab f | 1 | SELECT $1::TEXT t | 1 | SELECT pg_stat_monitor_reset() (4 rows) -- PL/pgSQL function - top-level tracking. SET pg_stat_monitor.pgsm_track = 'top'; SET pg_stat_monitor.pgsm_track_utility = FALSE; SELECT pg_stat_monitor_reset(); pg_stat_monitor_reset ----------------------- (1 row) CREATE FUNCTION PLUS_TWO(i INTEGER) RETURNS INTEGER AS $$ DECLARE r INTEGER; BEGIN SELECT (i + 1 + 1.0)::INTEGER INTO r; RETURN r; END; $$ LANGUAGE plpgsql; SELECT PLUS_TWO(3); plus_two ---------- 5 (1 row) SELECT PLUS_TWO(7); plus_two ---------- 9 (1 row) -- SQL function --- use LIMIT to keep it from being inlined CREATE FUNCTION PLUS_ONE(i INTEGER) RETURNS INTEGER AS $$ SELECT (i + 1.0)::INTEGER LIMIT 1 $$ LANGUAGE SQL; SELECT PLUS_ONE(8); plus_one ---------- 9 (1 row) SELECT PLUS_ONE(10); plus_one ---------- 11 (1 row) SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C"; calls | rows | query -------+------+-------------------------------- 2 | 2 | SELECT PLUS_ONE($1) 2 | 2 | SELECT PLUS_TWO($1) 1 | 1 | SELECT pg_stat_monitor_reset() (3 rows) -- immutable SQL function --- can be executed at plan time CREATE FUNCTION PLUS_THREE(i INTEGER) RETURNS INTEGER AS $$ SELECT i + 3 LIMIT 1 $$ IMMUTABLE LANGUAGE SQL; SELECT PLUS_THREE(8); plus_three ------------ 11 (1 row) SELECT PLUS_THREE(10); plus_three ------------ 13 (1 row) SELECT toplevel, calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C"; toplevel | calls | rows | query ----------+-------+------+--------------------------------------------------------------------------- t | 2 | 2 | SELECT PLUS_ONE($1) t | 2 | 2 | SELECT PLUS_THREE($1) t | 2 | 2 | SELECT PLUS_TWO($1) t | 1 | 3 | SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C" t | 1 | 1 | SELECT pg_stat_monitor_reset() (5 rows) -- PL/pgSQL function - all-level tracking. SET pg_stat_monitor.pgsm_track = 'all'; SELECT pg_stat_monitor_reset(); pg_stat_monitor_reset ----------------------- (1 row) -- we drop and recreate the functions to avoid any caching funnies DROP FUNCTION PLUS_ONE(INTEGER); DROP FUNCTION PLUS_TWO(INTEGER); DROP FUNCTION PLUS_THREE(INTEGER); -- PL/pgSQL function CREATE FUNCTION PLUS_TWO(i INTEGER) RETURNS INTEGER AS $$ DECLARE r INTEGER; BEGIN SELECT (i + 1 + 1.0)::INTEGER INTO r; RETURN r; END; $$ LANGUAGE plpgsql; SELECT PLUS_TWO(-1); plus_two ---------- 1 (1 row) SELECT PLUS_TWO(2); plus_two ---------- 4 (1 row) -- SQL function --- use LIMIT to keep it from being inlined CREATE FUNCTION PLUS_ONE(i INTEGER) RETURNS INTEGER AS $$ SELECT (i + 1.0)::INTEGER LIMIT 1 $$ LANGUAGE SQL; SELECT PLUS_ONE(3); plus_one ---------- 4 (1 row) SELECT PLUS_ONE(1); plus_one ---------- 2 (1 row) SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C"; calls | rows | query -------+------+----------------------------------- 2 | 2 | SELECT (i + $2 + $3)::INTEGER 2 | 2 | SELECT (i + $2)::INTEGER LIMIT $3 2 | 2 | SELECT PLUS_ONE($1) 2 | 2 | SELECT PLUS_TWO($1) 1 | 1 | SELECT pg_stat_monitor_reset() (5 rows) -- immutable SQL function --- can be executed at plan time CREATE FUNCTION PLUS_THREE(i INTEGER) RETURNS INTEGER AS $$ SELECT i + 3 LIMIT 1 $$ IMMUTABLE LANGUAGE SQL; SELECT PLUS_THREE(8); plus_three ------------ 11 (1 row) SELECT PLUS_THREE(10); plus_three ------------ 13 (1 row) SELECT toplevel, calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C"; toplevel | calls | rows | query ----------+-------+------+--------------------------------------------------------------------------- f | 2 | 2 | SELECT (i + $2 + $3)::INTEGER f | 2 | 2 | SELECT (i + $2)::INTEGER LIMIT $3 t | 2 | 2 | SELECT PLUS_ONE($1) t | 2 | 2 | SELECT PLUS_THREE($1) t | 2 | 2 | SELECT PLUS_TWO($1) t | 1 | 5 | SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C" f | 2 | 2 | SELECT i + $2 LIMIT $3 t | 1 | 1 | SELECT pg_stat_monitor_reset() (8 rows) -- -- pg_stat_monitor.pgsm_track = none -- SET pg_stat_monitor.pgsm_track = 'none'; SELECT pg_stat_monitor_reset(); pg_stat_monitor_reset ----------------------- (1 row) SELECT 1 AS "one"; one ----- 1 (1 row) SELECT 1 + 1 AS "two"; two ----- 2 (1 row) SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C"; calls | rows | query -------+------+------- (0 rows) SELECT pg_stat_monitor_reset(); pg_stat_monitor_reset ----------------------- (1 row) DROP EXTENSION pg_stat_monitor;