mirror of
https://github.com/postgres/postgres.git
synced 2025-05-29 00:03:09 -04:00
pgstat: add tests for transaction behaviour, 2PC, function stats.
Author: Andres Freund <andres@anarazel.de> Author: Melanie Plageman <melanieplageman@gmail.com> Discussion: https://postgr.es/m/20220303021600.hs34ghqcw6zcokdh@alap3.anarazel.de
This commit is contained in:
parent
ad401664b8
commit
e349c95d3e
3737
src/test/isolation/expected/stats.out
Normal file
3737
src/test/isolation/expected/stats.out
Normal file
File diff suppressed because it is too large
Load Diff
@ -89,6 +89,7 @@ test: timeouts
|
|||||||
test: vacuum-concurrent-drop
|
test: vacuum-concurrent-drop
|
||||||
test: vacuum-conflict
|
test: vacuum-conflict
|
||||||
test: vacuum-skip-locked
|
test: vacuum-skip-locked
|
||||||
|
test: stats
|
||||||
test: horizons
|
test: horizons
|
||||||
test: predicate-hash
|
test: predicate-hash
|
||||||
test: predicate-gist
|
test: predicate-gist
|
||||||
|
753
src/test/isolation/specs/stats.spec
Normal file
753
src/test/isolation/specs/stats.spec
Normal file
@ -0,0 +1,753 @@
|
|||||||
|
setup
|
||||||
|
{
|
||||||
|
CREATE TABLE test_stat_oid(name text NOT NULL, oid oid);
|
||||||
|
|
||||||
|
CREATE TABLE test_stat_tab(key text not null, value int);
|
||||||
|
INSERT INTO test_stat_tab(key, value) VALUES('k0', 1);
|
||||||
|
INSERT INTO test_stat_oid(name, oid) VALUES('test_stat_tab', 'test_stat_tab'::regclass);
|
||||||
|
|
||||||
|
CREATE FUNCTION test_stat_func() RETURNS VOID LANGUAGE plpgsql AS $$BEGIN END;$$;
|
||||||
|
INSERT INTO test_stat_oid(name, oid) VALUES('test_stat_func', 'test_stat_func'::regproc);
|
||||||
|
|
||||||
|
CREATE FUNCTION test_stat_func2() RETURNS VOID LANGUAGE plpgsql AS $$BEGIN END;$$;
|
||||||
|
INSERT INTO test_stat_oid(name, oid) VALUES('test_stat_func2', 'test_stat_func2'::regproc);
|
||||||
|
|
||||||
|
CREATE TABLE test_slru_stats(slru TEXT, stat TEXT, value INT);
|
||||||
|
|
||||||
|
SELECT pg_stat_force_next_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown
|
||||||
|
{
|
||||||
|
DROP TABLE test_stat_oid;
|
||||||
|
DROP TABLE test_slru_stats;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS test_stat_tab;
|
||||||
|
DROP FUNCTION IF EXISTS test_stat_func();
|
||||||
|
DROP FUNCTION IF EXISTS test_stat_func2();
|
||||||
|
}
|
||||||
|
|
||||||
|
session s1
|
||||||
|
setup { SET stats_fetch_consistency = 'none'; }
|
||||||
|
step s1_fetch_consistency_none { SET stats_fetch_consistency = 'none'; }
|
||||||
|
step s1_fetch_consistency_cache { SET stats_fetch_consistency = 'cache'; }
|
||||||
|
step s1_fetch_consistency_snapshot { SET stats_fetch_consistency = 'snapshot'; }
|
||||||
|
step s1_disable_debug_discard { SET debug_discard_caches = 0; }
|
||||||
|
step s1_clear_snapshot { SELECT pg_stat_clear_snapshot(); }
|
||||||
|
step s1_begin { BEGIN; }
|
||||||
|
step s1_commit { COMMIT; }
|
||||||
|
step s1_rollback { ROLLBACK; }
|
||||||
|
step s1_prepare_a { PREPARE TRANSACTION 'a'; }
|
||||||
|
step s1_commit_prepared_a { COMMIT PREPARED 'a'; }
|
||||||
|
step s1_rollback_prepared_a { ROLLBACK PREPARED 'a'; }
|
||||||
|
|
||||||
|
# Function stats steps
|
||||||
|
step s1_ff { SELECT pg_stat_force_next_flush(); RESET debug_discard_caches; }
|
||||||
|
step s1_track_funcs_all { SET track_functions = 'all'; }
|
||||||
|
step s1_track_funcs_none { SET track_functions = 'none'; }
|
||||||
|
step s1_func_call { SELECT test_stat_func(); }
|
||||||
|
step s1_func_drop { DROP FUNCTION test_stat_func(); }
|
||||||
|
step s1_func_stats_reset { SELECT pg_stat_reset_single_function_counters('test_stat_func'::regproc); }
|
||||||
|
step s1_func_stats_reset_nonexistent { SELECT pg_stat_reset_single_function_counters(12000); }
|
||||||
|
step s1_reset { SELECT pg_stat_reset(); }
|
||||||
|
step s1_func_stats {
|
||||||
|
SELECT
|
||||||
|
tso.name,
|
||||||
|
pg_stat_get_function_calls(tso.oid),
|
||||||
|
pg_stat_get_function_total_time(tso.oid) > 0 total_above_zero,
|
||||||
|
pg_stat_get_function_self_time(tso.oid) > 0 self_above_zero
|
||||||
|
FROM test_stat_oid AS tso
|
||||||
|
WHERE tso.name = 'test_stat_func'
|
||||||
|
}
|
||||||
|
step s1_func_stats2 {
|
||||||
|
SELECT
|
||||||
|
tso.name,
|
||||||
|
pg_stat_get_function_calls(tso.oid),
|
||||||
|
pg_stat_get_function_total_time(tso.oid) > 0 total_above_zero,
|
||||||
|
pg_stat_get_function_self_time(tso.oid) > 0 self_above_zero
|
||||||
|
FROM test_stat_oid AS tso
|
||||||
|
WHERE tso.name = 'test_stat_func2'
|
||||||
|
}
|
||||||
|
step s1_func_stats_nonexistent {
|
||||||
|
SELECT pg_stat_get_function_calls(12000);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Relation stats steps
|
||||||
|
step s1_track_counts_on { SET track_counts = on; }
|
||||||
|
step s1_track_counts_off { SET track_counts = off; }
|
||||||
|
step s1_table_select { SELECT * FROM test_stat_tab ORDER BY key, value; }
|
||||||
|
step s1_table_insert { INSERT INTO test_stat_tab(key, value) VALUES('k1', 1), ('k2', 1), ('k3', 1);}
|
||||||
|
step s1_table_insert_k1 { INSERT INTO test_stat_tab(key, value) VALUES('k1', 1);}
|
||||||
|
step s1_table_update_k1 { UPDATE test_stat_tab SET value = value + 1 WHERE key = 'k1';}
|
||||||
|
step s1_table_update_k2 { UPDATE test_stat_tab SET value = value + 1 WHERE key = 'k2';}
|
||||||
|
step s1_table_delete_k1 { DELETE FROM test_stat_tab WHERE key = 'k1';}
|
||||||
|
step s1_table_truncate { TRUNCATE test_stat_tab; }
|
||||||
|
step s1_table_drop { DROP TABLE test_stat_tab; }
|
||||||
|
|
||||||
|
step s1_table_stats {
|
||||||
|
SELECT
|
||||||
|
pg_stat_get_numscans(tso.oid) AS seq_scan,
|
||||||
|
pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
|
||||||
|
pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
|
||||||
|
pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
|
||||||
|
pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
|
||||||
|
pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
|
||||||
|
pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
|
||||||
|
pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
|
||||||
|
FROM test_stat_oid AS tso
|
||||||
|
WHERE tso.name = 'test_stat_tab'
|
||||||
|
}
|
||||||
|
|
||||||
|
# SLRU stats steps
|
||||||
|
step s1_slru_save_stats {
|
||||||
|
INSERT INTO test_slru_stats VALUES('Notify', 'blks_zeroed',
|
||||||
|
(SELECT blks_zeroed FROM pg_stat_slru WHERE name = 'Notify'));
|
||||||
|
}
|
||||||
|
step s1_listen { LISTEN stats_test_nothing; }
|
||||||
|
step s1_big_notify { SELECT pg_notify('stats_test_use',
|
||||||
|
repeat('0', current_setting('block_size')::int / 2)) FROM generate_series(1, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
step s1_slru_check_stats {
|
||||||
|
SELECT current.blks_zeroed > before.value
|
||||||
|
FROM test_slru_stats before
|
||||||
|
INNER JOIN pg_stat_slru current
|
||||||
|
ON before.slru = current.name
|
||||||
|
WHERE before.stat = 'blks_zeroed';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
session s2
|
||||||
|
setup { SET stats_fetch_consistency = 'none'; RESET debug_discard_caches; }
|
||||||
|
step s2_begin { BEGIN; }
|
||||||
|
step s2_disable_debug_discard { SET debug_discard_caches = 0; }
|
||||||
|
step s2_commit { COMMIT; }
|
||||||
|
step s2_commit_prepared_a { COMMIT PREPARED 'a'; }
|
||||||
|
step s2_rollback_prepared_a { ROLLBACK PREPARED 'a'; }
|
||||||
|
step s2_ff { SELECT pg_stat_force_next_flush(); }
|
||||||
|
|
||||||
|
# Function stats steps
|
||||||
|
step s2_track_funcs_all { SET track_functions = 'all'; }
|
||||||
|
step s2_track_funcs_none { SET track_functions = 'none'; }
|
||||||
|
step s2_func_call { SELECT test_stat_func() }
|
||||||
|
step s2_func_call2 { SELECT test_stat_func2() }
|
||||||
|
step s2_func_stats {
|
||||||
|
SELECT
|
||||||
|
tso.name,
|
||||||
|
pg_stat_get_function_calls(tso.oid),
|
||||||
|
pg_stat_get_function_total_time(tso.oid) > 0 total_above_zero,
|
||||||
|
pg_stat_get_function_self_time(tso.oid) > 0 self_above_zero
|
||||||
|
FROM test_stat_oid AS tso
|
||||||
|
WHERE tso.name = 'test_stat_func'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Relation stats steps
|
||||||
|
step s2_table_select { SELECT * FROM test_stat_tab ORDER BY key, value; }
|
||||||
|
step s2_table_update_k1 { UPDATE test_stat_tab SET value = value + 1 WHERE key = 'k1';}
|
||||||
|
|
||||||
|
# SLRU stats steps
|
||||||
|
step s2_big_notify { SELECT pg_notify('stats_test_use',
|
||||||
|
repeat('0', current_setting('block_size')::int / 2)) FROM generate_series(1, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
######################
|
||||||
|
# Function stats tests
|
||||||
|
######################
|
||||||
|
|
||||||
|
# check that stats are collected iff enabled
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_none s1_func_stats s1_func_call s1_func_call s1_ff s1_func_stats
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s1_func_stats s1_func_call s1_func_call s1_ff s1_func_stats
|
||||||
|
|
||||||
|
# multiple function calls are accurately reported, across separate connections
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all s1_func_stats s2_func_stats
|
||||||
|
s1_func_call s2_func_call s1_func_call s2_func_call s2_func_call s1_ff s2_ff s1_func_stats s2_func_stats
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all s1_func_stats s2_func_stats
|
||||||
|
s1_func_call s1_ff s2_func_call s2_func_call s2_ff s1_func_stats s2_func_stats
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all s1_func_stats s2_func_stats
|
||||||
|
s1_begin s1_func_call s1_func_call s1_commit s1_ff s1_func_stats s2_func_stats
|
||||||
|
|
||||||
|
|
||||||
|
### Check interaction between dropping and stats reporting
|
||||||
|
|
||||||
|
# Disable debug_discard_caches for a few of these tests - we precisely are
|
||||||
|
# testing the behavior of no invalidations arriving. "Real" invalidations
|
||||||
|
# shouldn't trigger behavioral difference, because we are testing paths
|
||||||
|
# precisely because they do not have AcceptInvalidationMessages calls.()
|
||||||
|
|
||||||
|
# dropping a table remove stats iff committed
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all s1_func_stats s2_func_stats
|
||||||
|
s1_begin s1_func_call s2_func_call s1_func_drop s2_func_call s2_ff s2_func_stats s1_commit s1_ff s1_func_stats s2_func_stats
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all s1_func_stats s2_func_stats
|
||||||
|
s1_begin s1_func_call s2_func_call s1_func_drop s2_func_call s2_ff s2_func_stats s1_rollback s1_ff s1_func_stats s2_func_stats
|
||||||
|
|
||||||
|
# Verify that pending stats from before a drop do not lead to
|
||||||
|
# reviving stats for a dropped object
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s2_func_call s2_ff # this access increments refcount, preventing the shared entry from being dropped
|
||||||
|
s2_begin s2_func_call s1_func_drop s1_func_stats s2_commit s2_ff s1_func_stats s2_func_stats
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s2_begin s2_func_call s1_func_drop s1_func_stats s2_commit s2_ff s1_func_stats s2_func_stats
|
||||||
|
permutation
|
||||||
|
s1_disable_debug_discard s2_disable_debug_discard
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s1_func_call s2_begin s2_func_call s1_func_drop s2_func_call s2_commit s2_ff s1_func_stats s2_func_stats
|
||||||
|
|
||||||
|
# Function calls don't necessarily trigger cache invalidation processing. The
|
||||||
|
# default handling of dropped stats could therefore end up with stats getting
|
||||||
|
# revived by a function call done after stats processing - but
|
||||||
|
# pgstat_init_function_usage() protects against that if track_functions is
|
||||||
|
# on. Verify that the stats are indeed dropped, and document the behavioral
|
||||||
|
# difference between track_functions settings.
|
||||||
|
permutation
|
||||||
|
s1_disable_debug_discard s2_disable_debug_discard
|
||||||
|
s1_track_funcs_all s2_track_funcs_none
|
||||||
|
s1_func_call s2_begin s2_func_call s1_ff s1_func_stats s1_func_drop s2_track_funcs_none s1_func_stats s2_func_call s2_commit s2_ff s1_func_stats s2_func_stats
|
||||||
|
permutation
|
||||||
|
s1_disable_debug_discard s2_disable_debug_discard
|
||||||
|
s1_track_funcs_all s2_track_funcs_none
|
||||||
|
s1_func_call s2_begin s2_func_call s1_ff s1_func_stats s1_func_drop s2_track_funcs_all s1_func_stats s2_func_call s2_commit s2_ff s1_func_stats s2_func_stats
|
||||||
|
|
||||||
|
# test pg_stat_reset_single_function_counters
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s1_func_call
|
||||||
|
s2_func_call
|
||||||
|
s2_func_call2
|
||||||
|
s1_ff s2_ff
|
||||||
|
s1_func_stats
|
||||||
|
s2_func_call s2_func_call2 s2_ff
|
||||||
|
s1_func_stats s1_func_stats2 s1_func_stats
|
||||||
|
s1_func_stats_reset
|
||||||
|
s1_func_stats s1_func_stats2 s1_func_stats
|
||||||
|
|
||||||
|
# test pg_stat_reset_single_function_counters of non-existing function
|
||||||
|
permutation
|
||||||
|
s1_func_stats_nonexistent
|
||||||
|
s1_func_stats_reset_nonexistent
|
||||||
|
s1_func_stats_nonexistent
|
||||||
|
|
||||||
|
# test pg_stat_reset
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s1_func_call
|
||||||
|
s2_func_call
|
||||||
|
s2_func_call2
|
||||||
|
s1_ff s2_ff
|
||||||
|
s1_func_stats s1_func_stats2 s1_func_stats
|
||||||
|
s1_reset
|
||||||
|
s1_func_stats s1_func_stats2 s1_func_stats
|
||||||
|
|
||||||
|
|
||||||
|
### Check the different snapshot consistency models
|
||||||
|
|
||||||
|
# First just some dead-trivial test verifying each model doesn't crash
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s1_fetch_consistency_none s1_func_call s1_ff s1_func_stats
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s1_fetch_consistency_cache s1_func_call s1_ff s1_func_stats
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s1_fetch_consistency_snapshot s1_func_call s1_ff s1_func_stats
|
||||||
|
|
||||||
|
# with stats_fetch_consistency=none s1 should see flushed changes in s2, despite being in a transaction
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s1_fetch_consistency_none
|
||||||
|
s2_func_call s2_ff
|
||||||
|
s1_begin
|
||||||
|
s1_func_stats
|
||||||
|
s2_func_call s2_ff
|
||||||
|
s1_func_stats
|
||||||
|
s1_commit
|
||||||
|
|
||||||
|
# with stats_fetch_consistency=cache s1 should not see concurrent
|
||||||
|
# changes to the same object after the first access, but a separate
|
||||||
|
# object should show changes
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s1_fetch_consistency_cache
|
||||||
|
s2_func_call s2_func_call2 s2_ff
|
||||||
|
s1_begin
|
||||||
|
s1_func_stats
|
||||||
|
s2_func_call s2_func_call2 s2_ff
|
||||||
|
s1_func_stats s1_func_stats2
|
||||||
|
s1_commit
|
||||||
|
|
||||||
|
# with stats_fetch_consistency=snapshot s1 should not see any
|
||||||
|
# concurrent changes after the first access
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s1_fetch_consistency_snapshot
|
||||||
|
s2_func_call s2_func_call2 s2_ff
|
||||||
|
s1_begin
|
||||||
|
s1_func_stats
|
||||||
|
s2_func_call s2_func_call2 s2_ff
|
||||||
|
s1_func_stats s1_func_stats2
|
||||||
|
s1_commit
|
||||||
|
|
||||||
|
# Check access to non-existing stats works correctly and repeatedly
|
||||||
|
permutation
|
||||||
|
s1_fetch_consistency_none
|
||||||
|
s1_begin
|
||||||
|
s1_func_stats_nonexistent
|
||||||
|
s1_func_stats_nonexistent
|
||||||
|
s1_commit
|
||||||
|
permutation
|
||||||
|
s1_fetch_consistency_cache
|
||||||
|
s1_begin
|
||||||
|
s1_func_stats_nonexistent
|
||||||
|
s1_func_stats_nonexistent
|
||||||
|
s1_commit
|
||||||
|
permutation
|
||||||
|
s1_fetch_consistency_snapshot
|
||||||
|
s1_begin
|
||||||
|
s1_func_stats_nonexistent
|
||||||
|
s1_func_stats_nonexistent
|
||||||
|
s1_commit
|
||||||
|
|
||||||
|
|
||||||
|
### Check 2PC handling of stat drops
|
||||||
|
|
||||||
|
# S1 prepared, S1 commits prepared
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s1_begin
|
||||||
|
s1_func_call
|
||||||
|
s2_func_call
|
||||||
|
s1_func_drop
|
||||||
|
s2_func_call
|
||||||
|
s2_ff
|
||||||
|
s1_prepare_a
|
||||||
|
s2_func_call
|
||||||
|
s2_ff
|
||||||
|
s1_func_call
|
||||||
|
s1_ff
|
||||||
|
s1_func_stats
|
||||||
|
s1_commit_prepared_a
|
||||||
|
s1_func_stats
|
||||||
|
|
||||||
|
# S1 prepared, S1 aborts prepared
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s1_begin
|
||||||
|
s1_func_call
|
||||||
|
s2_func_call
|
||||||
|
s1_func_drop
|
||||||
|
s2_func_call
|
||||||
|
s2_ff
|
||||||
|
s1_prepare_a
|
||||||
|
s2_func_call
|
||||||
|
s2_ff
|
||||||
|
s1_func_call
|
||||||
|
s1_ff
|
||||||
|
s1_func_stats
|
||||||
|
s1_rollback_prepared_a
|
||||||
|
s1_func_stats
|
||||||
|
|
||||||
|
# S1 prepares, S2 commits prepared
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s1_begin
|
||||||
|
s1_func_call
|
||||||
|
s2_func_call
|
||||||
|
s1_func_drop
|
||||||
|
s2_func_call
|
||||||
|
s2_ff
|
||||||
|
s1_prepare_a
|
||||||
|
s2_func_call
|
||||||
|
s2_ff
|
||||||
|
s1_func_call
|
||||||
|
s1_ff
|
||||||
|
s1_func_stats
|
||||||
|
s2_commit_prepared_a
|
||||||
|
s1_func_stats
|
||||||
|
|
||||||
|
# S1 prepared, S2 aborts prepared
|
||||||
|
permutation
|
||||||
|
s1_track_funcs_all s2_track_funcs_all
|
||||||
|
s1_begin
|
||||||
|
s1_func_call
|
||||||
|
s2_func_call
|
||||||
|
s1_func_drop
|
||||||
|
s2_func_call
|
||||||
|
s2_ff
|
||||||
|
s1_prepare_a
|
||||||
|
s2_func_call
|
||||||
|
s2_ff
|
||||||
|
s1_func_call
|
||||||
|
s1_ff
|
||||||
|
s1_func_stats
|
||||||
|
s2_rollback_prepared_a
|
||||||
|
s1_func_stats
|
||||||
|
|
||||||
|
|
||||||
|
######################
|
||||||
|
# Table stats tests
|
||||||
|
######################
|
||||||
|
|
||||||
|
# Most of the stats handling mechanism has already been tested in the function
|
||||||
|
# stats tests above - that's cheaper than testing with relations. But
|
||||||
|
# particularly for 2PC there are special cases
|
||||||
|
|
||||||
|
|
||||||
|
### Verify that pending stats from before a drop do not lead to reviving
|
||||||
|
### of stats for a dropped object
|
||||||
|
|
||||||
|
permutation
|
||||||
|
s1_table_select
|
||||||
|
s1_table_insert
|
||||||
|
s2_table_select
|
||||||
|
s2_table_update_k1
|
||||||
|
s1_ff
|
||||||
|
s2_table_update_k1
|
||||||
|
s1_table_drop
|
||||||
|
s2_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
permutation
|
||||||
|
s1_table_select
|
||||||
|
s1_table_insert
|
||||||
|
s2_table_select
|
||||||
|
s2_table_update_k1
|
||||||
|
s2_table_update_k1
|
||||||
|
s1_table_drop
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
|
||||||
|
### Check that we don't count changes with track counts off, but allow access
|
||||||
|
### to prior stats
|
||||||
|
|
||||||
|
# simple read access with stats off
|
||||||
|
permutation
|
||||||
|
s1_track_counts_off
|
||||||
|
s1_table_stats
|
||||||
|
s1_track_counts_on
|
||||||
|
|
||||||
|
# simple read access with stats off, previously accessed
|
||||||
|
permutation
|
||||||
|
s1_table_select
|
||||||
|
s1_track_counts_off
|
||||||
|
s1_ff
|
||||||
|
s1_table_stats
|
||||||
|
s1_track_counts_on
|
||||||
|
permutation
|
||||||
|
s1_table_select
|
||||||
|
s1_ff
|
||||||
|
s1_track_counts_off
|
||||||
|
s1_table_stats
|
||||||
|
s1_track_counts_on
|
||||||
|
|
||||||
|
# ensure we don't count anything with stats off
|
||||||
|
permutation
|
||||||
|
s1_track_counts_off
|
||||||
|
s1_table_select
|
||||||
|
s1_table_insert_k1
|
||||||
|
s1_table_update_k1
|
||||||
|
s2_table_select
|
||||||
|
s1_track_counts_on
|
||||||
|
s1_ff s2_ff
|
||||||
|
s1_table_stats
|
||||||
|
# but can count again after
|
||||||
|
s1_table_select
|
||||||
|
s1_table_update_k1
|
||||||
|
s1_ff
|
||||||
|
s1_table_stats
|
||||||
|
permutation
|
||||||
|
s1_table_select
|
||||||
|
s1_table_insert_k1
|
||||||
|
s1_table_delete_k1
|
||||||
|
s1_track_counts_off
|
||||||
|
s1_table_select
|
||||||
|
s1_table_insert_k1
|
||||||
|
s1_table_update_k1
|
||||||
|
s2_table_select
|
||||||
|
s1_track_counts_on
|
||||||
|
s1_ff s2_ff
|
||||||
|
s1_table_stats
|
||||||
|
s1_table_select
|
||||||
|
s1_table_update_k1
|
||||||
|
s1_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
|
||||||
|
### 2PC: transactional and non-transactional counters work correctly
|
||||||
|
|
||||||
|
# S1 prepares, S2 commits prepared
|
||||||
|
permutation
|
||||||
|
s1_begin
|
||||||
|
s1_table_insert s1_table_update_k1 s1_table_update_k1 s1_table_update_k2 s1_table_update_k2 s1_table_update_k2 s1_table_delete_k1
|
||||||
|
s1_table_select
|
||||||
|
s1_prepare_a
|
||||||
|
s1_table_select
|
||||||
|
s1_commit_prepared_a
|
||||||
|
s1_table_select
|
||||||
|
s1_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
# S1 prepares, S2 commits prepared
|
||||||
|
permutation
|
||||||
|
s1_begin
|
||||||
|
s1_table_insert s1_table_update_k1 s1_table_update_k1 s1_table_update_k2 s1_table_update_k2 s1_table_update_k2 s1_table_delete_k1
|
||||||
|
s1_table_select
|
||||||
|
s1_prepare_a
|
||||||
|
s1_table_select
|
||||||
|
s2_commit_prepared_a
|
||||||
|
s1_table_select
|
||||||
|
s1_ff s2_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
# S1 prepares, S2 commits prepared
|
||||||
|
permutation
|
||||||
|
s1_begin
|
||||||
|
s1_table_insert s1_table_update_k1 s1_table_update_k1 s1_table_update_k2 s1_table_update_k2 s1_table_update_k2 s1_table_delete_k1
|
||||||
|
s1_table_select
|
||||||
|
s1_prepare_a
|
||||||
|
s1_table_select
|
||||||
|
s1_rollback_prepared_a
|
||||||
|
s1_table_select
|
||||||
|
s1_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
# S1 prepares, S1 aborts prepared
|
||||||
|
permutation
|
||||||
|
s1_begin
|
||||||
|
s1_table_insert s1_table_update_k1 s1_table_update_k1 s1_table_update_k2 s1_table_update_k2 s1_table_update_k2 s1_table_delete_k1
|
||||||
|
s1_table_select
|
||||||
|
s1_prepare_a
|
||||||
|
s1_table_select
|
||||||
|
s2_rollback_prepared_a
|
||||||
|
s1_table_select
|
||||||
|
s1_ff s2_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
|
||||||
|
### 2PC: truncate handling
|
||||||
|
|
||||||
|
# S1 prepares, S1 commits prepared
|
||||||
|
permutation
|
||||||
|
s1_table_insert
|
||||||
|
s1_begin
|
||||||
|
s1_table_update_k1 # should *not* be counted, different rel
|
||||||
|
s1_table_update_k1 # dito
|
||||||
|
s1_table_truncate
|
||||||
|
s1_table_insert_k1 # should be counted
|
||||||
|
s1_table_update_k1 # dito
|
||||||
|
s1_prepare_a
|
||||||
|
s1_commit_prepared_a
|
||||||
|
s1_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
# S1 prepares, S2 commits prepared
|
||||||
|
permutation
|
||||||
|
s1_table_insert
|
||||||
|
s1_begin
|
||||||
|
s1_table_update_k1 # should *not* be counted, different rel
|
||||||
|
s1_table_update_k1 # dito
|
||||||
|
s1_table_truncate
|
||||||
|
s1_table_insert_k1 # should be counted
|
||||||
|
s1_table_update_k1 # dito
|
||||||
|
s1_prepare_a
|
||||||
|
s2_commit_prepared_a
|
||||||
|
s1_ff s2_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
# S1 prepares, S1 aborts prepared
|
||||||
|
permutation
|
||||||
|
s1_table_insert
|
||||||
|
s1_begin
|
||||||
|
s1_table_update_k1 # should be counted
|
||||||
|
s1_table_update_k1 # dito
|
||||||
|
s1_table_truncate
|
||||||
|
s1_table_insert_k1 # should *not* be counted, different rel
|
||||||
|
s1_table_update_k1 # dito
|
||||||
|
s1_prepare_a
|
||||||
|
s1_rollback_prepared_a
|
||||||
|
s1_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
# S1 prepares, S2 aborts prepared
|
||||||
|
permutation
|
||||||
|
s1_table_insert
|
||||||
|
s1_begin
|
||||||
|
s1_table_update_k1 # should be counted
|
||||||
|
s1_table_update_k1 # dito
|
||||||
|
s1_table_truncate
|
||||||
|
s1_table_insert_k1 # should *not* be counted, different rel
|
||||||
|
s1_table_update_k1 # dito
|
||||||
|
s1_prepare_a
|
||||||
|
s2_rollback_prepared_a
|
||||||
|
s1_ff s2_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
|
||||||
|
### 2PC: rolled back drop maintains live / dead counters
|
||||||
|
|
||||||
|
# S1 prepares, S1 aborts prepared
|
||||||
|
permutation
|
||||||
|
s1_table_insert
|
||||||
|
s1_table_update_k1
|
||||||
|
s1_begin
|
||||||
|
# should all be counted
|
||||||
|
s1_table_delete_k1
|
||||||
|
s1_table_insert_k1
|
||||||
|
s1_table_update_k1
|
||||||
|
s1_table_update_k1
|
||||||
|
s1_table_drop
|
||||||
|
s1_prepare_a
|
||||||
|
s1_rollback_prepared_a
|
||||||
|
s1_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
# S1 prepares, S1 aborts prepared
|
||||||
|
permutation
|
||||||
|
s1_table_insert
|
||||||
|
s1_table_update_k1
|
||||||
|
s1_begin
|
||||||
|
# should all be counted
|
||||||
|
s1_table_delete_k1
|
||||||
|
s1_table_insert_k1
|
||||||
|
s1_table_update_k1
|
||||||
|
s1_table_update_k1
|
||||||
|
s1_table_drop
|
||||||
|
s1_prepare_a
|
||||||
|
s2_rollback_prepared_a
|
||||||
|
s1_ff s2_ff
|
||||||
|
s1_table_stats
|
||||||
|
|
||||||
|
|
||||||
|
######################
|
||||||
|
# SLRU stats tests
|
||||||
|
######################
|
||||||
|
|
||||||
|
# Verify SLRU stats generated in own transaction
|
||||||
|
permutation
|
||||||
|
s1_slru_save_stats
|
||||||
|
s1_listen
|
||||||
|
s1_begin
|
||||||
|
s1_big_notify
|
||||||
|
s1_ff
|
||||||
|
s1_slru_check_stats
|
||||||
|
s1_commit
|
||||||
|
s1_slru_check_stats
|
||||||
|
|
||||||
|
# Verify SLRU stats generated in separate transaction
|
||||||
|
permutation
|
||||||
|
s1_slru_save_stats
|
||||||
|
s1_listen
|
||||||
|
s2_big_notify
|
||||||
|
s2_ff
|
||||||
|
s1_slru_check_stats
|
||||||
|
|
||||||
|
# shouldn't see stats yet, not committed
|
||||||
|
permutation
|
||||||
|
s1_slru_save_stats
|
||||||
|
s1_listen
|
||||||
|
s2_begin
|
||||||
|
s2_big_notify
|
||||||
|
s2_ff
|
||||||
|
s1_slru_check_stats
|
||||||
|
s2_commit
|
||||||
|
|
||||||
|
|
||||||
|
### Check the different snapshot consistency models for fixed-amount statistics
|
||||||
|
|
||||||
|
permutation
|
||||||
|
s1_fetch_consistency_none
|
||||||
|
s1_slru_save_stats s1_listen
|
||||||
|
s1_begin
|
||||||
|
s1_slru_check_stats
|
||||||
|
s2_big_notify
|
||||||
|
s2_ff
|
||||||
|
s1_slru_check_stats
|
||||||
|
s1_commit
|
||||||
|
s1_slru_check_stats
|
||||||
|
permutation
|
||||||
|
s1_fetch_consistency_cache
|
||||||
|
s1_slru_save_stats s1_listen
|
||||||
|
s1_begin
|
||||||
|
s1_slru_check_stats
|
||||||
|
s2_big_notify
|
||||||
|
s2_ff
|
||||||
|
s1_slru_check_stats
|
||||||
|
s1_commit
|
||||||
|
s1_slru_check_stats
|
||||||
|
permutation
|
||||||
|
s1_fetch_consistency_snapshot
|
||||||
|
s1_slru_save_stats s1_listen
|
||||||
|
s1_begin
|
||||||
|
s1_slru_check_stats
|
||||||
|
s2_big_notify
|
||||||
|
s2_ff
|
||||||
|
s1_slru_check_stats
|
||||||
|
s1_commit
|
||||||
|
s1_slru_check_stats
|
||||||
|
|
||||||
|
# check that pg_stat_clear_snapshot(), well ...
|
||||||
|
permutation
|
||||||
|
s1_fetch_consistency_none
|
||||||
|
s1_slru_save_stats s1_listen
|
||||||
|
s1_begin
|
||||||
|
s1_slru_check_stats
|
||||||
|
s2_big_notify
|
||||||
|
s2_ff
|
||||||
|
s1_slru_check_stats
|
||||||
|
s1_clear_snapshot
|
||||||
|
s1_slru_check_stats
|
||||||
|
s1_commit
|
||||||
|
permutation
|
||||||
|
s1_fetch_consistency_cache
|
||||||
|
s1_slru_save_stats s1_listen
|
||||||
|
s1_begin
|
||||||
|
s1_slru_check_stats
|
||||||
|
s2_big_notify
|
||||||
|
s2_ff
|
||||||
|
s1_slru_check_stats
|
||||||
|
s1_clear_snapshot
|
||||||
|
s1_slru_check_stats
|
||||||
|
s1_commit
|
||||||
|
permutation
|
||||||
|
s1_fetch_consistency_snapshot
|
||||||
|
s1_slru_save_stats s1_listen
|
||||||
|
s1_begin
|
||||||
|
s1_slru_check_stats
|
||||||
|
s2_big_notify
|
||||||
|
s2_ff
|
||||||
|
s1_slru_check_stats
|
||||||
|
s1_clear_snapshot
|
||||||
|
s1_slru_check_stats
|
||||||
|
s1_commit
|
||||||
|
|
||||||
|
# check that a variable-amount stats access caches fixed-amount stat too
|
||||||
|
permutation
|
||||||
|
s1_fetch_consistency_snapshot
|
||||||
|
s1_slru_save_stats s1_listen
|
||||||
|
s1_begin
|
||||||
|
s1_func_stats
|
||||||
|
s2_big_notify
|
||||||
|
s2_ff
|
||||||
|
s1_slru_check_stats
|
||||||
|
s1_commit
|
||||||
|
|
||||||
|
# and the other way round
|
||||||
|
permutation
|
||||||
|
s1_fetch_consistency_snapshot
|
||||||
|
s1_slru_save_stats s1_listen
|
||||||
|
s1_begin
|
||||||
|
s2_big_notify
|
||||||
|
s2_ff
|
||||||
|
s1_slru_check_stats
|
||||||
|
s2_func_call
|
||||||
|
s2_ff
|
||||||
|
s1_func_stats
|
||||||
|
s1_clear_snapshot
|
||||||
|
s1_func_stats
|
||||||
|
s1_commit
|
@ -16,6 +16,8 @@ SET enable_seqscan TO on;
|
|||||||
SET enable_indexscan TO on;
|
SET enable_indexscan TO on;
|
||||||
-- for the moment, we don't want index-only scans here
|
-- for the moment, we don't want index-only scans here
|
||||||
SET enable_indexonlyscan TO off;
|
SET enable_indexonlyscan TO off;
|
||||||
|
-- not enabled by default, but we want to test it...
|
||||||
|
SET track_functions TO 'all';
|
||||||
-- save counters
|
-- save counters
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET LOCAL stats_fetch_consistency = snapshot;
|
SET LOCAL stats_fetch_consistency = snapshot;
|
||||||
@ -146,8 +148,477 @@ FROM prevstats AS pr;
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
----
|
||||||
|
-- Basic tests for track_functions
|
||||||
|
---
|
||||||
|
CREATE FUNCTION stats_test_func1() RETURNS VOID LANGUAGE plpgsql AS $$BEGIN END;$$;
|
||||||
|
SELECT 'stats_test_func1()'::regprocedure::oid AS stats_test_func1_oid \gset
|
||||||
|
CREATE FUNCTION stats_test_func2() RETURNS VOID LANGUAGE plpgsql AS $$BEGIN END;$$;
|
||||||
|
SELECT 'stats_test_func2()'::regprocedure::oid AS stats_test_func2_oid \gset
|
||||||
|
-- test that stats are accumulated
|
||||||
|
BEGIN;
|
||||||
|
SET LOCAL stats_fetch_consistency = none;
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func1_oid);
|
||||||
|
pg_stat_get_function_calls
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid);
|
||||||
|
pg_stat_get_xact_function_calls
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT stats_test_func1();
|
||||||
|
stats_test_func1
|
||||||
|
------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid);
|
||||||
|
pg_stat_get_xact_function_calls
|
||||||
|
---------------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT stats_test_func1();
|
||||||
|
stats_test_func1
|
||||||
|
------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid);
|
||||||
|
pg_stat_get_xact_function_calls
|
||||||
|
---------------------------------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func1_oid);
|
||||||
|
pg_stat_get_function_calls
|
||||||
|
----------------------------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
-- Verify that function stats are not transactional
|
||||||
|
-- rolled back savepoint in committing transaction
|
||||||
|
BEGIN;
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
stats_test_func2
|
||||||
|
------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SAVEPOINT foo;
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
stats_test_func2
|
||||||
|
------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
ROLLBACK TO SAVEPOINT foo;
|
||||||
|
SELECT pg_stat_get_xact_function_calls(:stats_test_func2_oid);
|
||||||
|
pg_stat_get_xact_function_calls
|
||||||
|
---------------------------------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
stats_test_func2
|
||||||
|
------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
-- rolled back transaction
|
||||||
|
BEGIN;
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
stats_test_func2
|
||||||
|
------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
ROLLBACK;
|
||||||
|
SELECT pg_stat_force_next_flush();
|
||||||
|
pg_stat_force_next_flush
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- check collected stats
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid;
|
||||||
|
funcname | calls
|
||||||
|
------------------+-------
|
||||||
|
stats_test_func1 | 2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func2_oid;
|
||||||
|
funcname | calls
|
||||||
|
------------------+-------
|
||||||
|
stats_test_func2 | 4
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- check that a rolled back drop function stats leaves stats alive
|
||||||
|
BEGIN;
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid;
|
||||||
|
funcname | calls
|
||||||
|
------------------+-------
|
||||||
|
stats_test_func1 | 2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
DROP FUNCTION stats_test_func1();
|
||||||
|
-- shouldn't be visible via view
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid;
|
||||||
|
funcname | calls
|
||||||
|
----------+-------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
-- but still via oid access
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func1_oid);
|
||||||
|
pg_stat_get_function_calls
|
||||||
|
----------------------------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
ROLLBACK;
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid;
|
||||||
|
funcname | calls
|
||||||
|
------------------+-------
|
||||||
|
stats_test_func1 | 2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func1_oid);
|
||||||
|
pg_stat_get_function_calls
|
||||||
|
----------------------------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- check that function dropped in main transaction leaves no stats behind
|
||||||
|
BEGIN;
|
||||||
|
DROP FUNCTION stats_test_func1();
|
||||||
|
COMMIT;
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid;
|
||||||
|
funcname | calls
|
||||||
|
----------+-------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func1_oid);
|
||||||
|
pg_stat_get_function_calls
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- check that function dropped in a subtransaction leaves no stats behind
|
||||||
|
BEGIN;
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
stats_test_func2
|
||||||
|
------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SAVEPOINT a;
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
stats_test_func2
|
||||||
|
------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SAVEPOINT b;
|
||||||
|
DROP FUNCTION stats_test_func2();
|
||||||
|
COMMIT;
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func2_oid;
|
||||||
|
funcname | calls
|
||||||
|
----------+-------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func2_oid);
|
||||||
|
pg_stat_get_function_calls
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- Check that stats for relations are dropped. For that we need to access stats
|
||||||
|
-- by oid after the DROP TABLE. Save oids.
|
||||||
|
CREATE TABLE drop_stats_test();
|
||||||
|
INSERT INTO drop_stats_test DEFAULT VALUES;
|
||||||
|
SELECT 'drop_stats_test'::regclass::oid AS drop_stats_test_oid \gset
|
||||||
|
CREATE TABLE drop_stats_test_xact();
|
||||||
|
INSERT INTO drop_stats_test_xact DEFAULT VALUES;
|
||||||
|
SELECT 'drop_stats_test_xact'::regclass::oid AS drop_stats_test_xact_oid \gset
|
||||||
|
CREATE TABLE drop_stats_test_subxact();
|
||||||
|
INSERT INTO drop_stats_test_subxact DEFAULT VALUES;
|
||||||
|
SELECT 'drop_stats_test_subxact'::regclass::oid AS drop_stats_test_subxact_oid \gset
|
||||||
|
SELECT pg_stat_force_next_flush();
|
||||||
|
pg_stat_force_next_flush
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
DROP TABLE drop_stats_test;
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_oid);
|
||||||
|
pg_stat_get_xact_tuples_inserted
|
||||||
|
----------------------------------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- check that rollback protects against having stats dropped and that local
|
||||||
|
-- modifications don't pose a problem
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_tuples_inserted
|
||||||
|
-----------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_xact_tuples_inserted
|
||||||
|
----------------------------------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO drop_stats_test_xact DEFAULT VALUES;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_xact_tuples_inserted
|
||||||
|
----------------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
DROP TABLE drop_stats_test_xact;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_xact_tuples_inserted
|
||||||
|
----------------------------------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
ROLLBACK;
|
||||||
|
SELECT pg_stat_force_next_flush();
|
||||||
|
pg_stat_force_next_flush
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_tuples_inserted
|
||||||
|
-----------------------------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- transactional drop
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_tuples_inserted
|
||||||
|
-----------------------------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO drop_stats_test_xact DEFAULT VALUES;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_xact_tuples_inserted
|
||||||
|
----------------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
DROP TABLE drop_stats_test_xact;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_xact_tuples_inserted
|
||||||
|
----------------------------------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
SELECT pg_stat_force_next_flush();
|
||||||
|
pg_stat_force_next_flush
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
pg_stat_get_tuples_inserted
|
||||||
|
-----------------------------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- savepoint rollback (2 levels)
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO drop_stats_test_subxact DEFAULT VALUES;
|
||||||
|
SAVEPOINT sp1;
|
||||||
|
INSERT INTO drop_stats_test_subxact DEFAULT VALUES;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_subxact_oid);
|
||||||
|
pg_stat_get_xact_tuples_inserted
|
||||||
|
----------------------------------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SAVEPOINT sp2;
|
||||||
|
DROP TABLE drop_stats_test_subxact;
|
||||||
|
ROLLBACK TO SAVEPOINT sp2;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_subxact_oid);
|
||||||
|
pg_stat_get_xact_tuples_inserted
|
||||||
|
----------------------------------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
SELECT pg_stat_force_next_flush();
|
||||||
|
pg_stat_force_next_flush
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- savepoint rolback (1 level)
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
SAVEPOINT sp1;
|
||||||
|
DROP TABLE drop_stats_test_subxact;
|
||||||
|
SAVEPOINT sp2;
|
||||||
|
ROLLBACK TO SAVEPOINT sp1;
|
||||||
|
COMMIT;
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- and now actually drop
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
SAVEPOINT sp1;
|
||||||
|
DROP TABLE drop_stats_test_subxact;
|
||||||
|
SAVEPOINT sp2;
|
||||||
|
RELEASE SAVEPOINT sp1;
|
||||||
|
COMMIT;
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
pg_stat_get_live_tuples
|
||||||
|
-------------------------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
DROP TABLE trunc_stats_test, trunc_stats_test1, trunc_stats_test2, trunc_stats_test3, trunc_stats_test4;
|
DROP TABLE trunc_stats_test, trunc_stats_test1, trunc_stats_test2, trunc_stats_test3, trunc_stats_test4;
|
||||||
DROP TABLE prevstats;
|
DROP TABLE prevstats;
|
||||||
|
----
|
||||||
|
-- pg_stat_get_snapshot_timestamp behavior
|
||||||
|
----
|
||||||
|
BEGIN;
|
||||||
|
SET LOCAL stats_fetch_consistency = snapshot;
|
||||||
|
-- no snapshot yet, return NULL
|
||||||
|
SELECT pg_stat_get_snapshot_timestamp();
|
||||||
|
pg_stat_get_snapshot_timestamp
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- any attempt at accessing stats will build snapshot
|
||||||
|
SELECT pg_stat_get_function_calls(0);
|
||||||
|
pg_stat_get_function_calls
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_snapshot_timestamp() >= NOW();
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- shows NULL again after clearing
|
||||||
|
SELECT pg_stat_clear_snapshot();
|
||||||
|
pg_stat_clear_snapshot
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_get_snapshot_timestamp();
|
||||||
|
pg_stat_get_snapshot_timestamp
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
----
|
||||||
|
-- pg_stat_have_stats behavior
|
||||||
|
----
|
||||||
|
-- fixed-numbered stats exist
|
||||||
|
SELECT pg_stat_have_stats('bgwriter', 0, 0);
|
||||||
|
pg_stat_have_stats
|
||||||
|
--------------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- unknown stats kinds error out
|
||||||
|
SELECT pg_stat_have_stats('zaphod', 0, 0);
|
||||||
|
ERROR: invalid statistics kind: "zaphod"
|
||||||
|
-- db stats have objoid 0
|
||||||
|
SELECT pg_stat_have_stats('database', (SELECT oid FROM pg_database WHERE datname = current_database()), 1);
|
||||||
|
pg_stat_have_stats
|
||||||
|
--------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_have_stats('database', (SELECT oid FROM pg_database WHERE datname = current_database()), 0);
|
||||||
|
pg_stat_have_stats
|
||||||
|
--------------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- ensure that stats accessors handle NULL input correctly
|
-- ensure that stats accessors handle NULL input correctly
|
||||||
SELECT pg_stat_get_replication_slot(NULL);
|
SELECT pg_stat_get_replication_slot(NULL);
|
||||||
pg_stat_get_replication_slot
|
pg_stat_get_replication_slot
|
||||||
|
@ -13,6 +13,8 @@ SET enable_seqscan TO on;
|
|||||||
SET enable_indexscan TO on;
|
SET enable_indexscan TO on;
|
||||||
-- for the moment, we don't want index-only scans here
|
-- for the moment, we don't want index-only scans here
|
||||||
SET enable_indexonlyscan TO off;
|
SET enable_indexonlyscan TO off;
|
||||||
|
-- not enabled by default, but we want to test it...
|
||||||
|
SET track_functions TO 'all';
|
||||||
|
|
||||||
-- save counters
|
-- save counters
|
||||||
BEGIN;
|
BEGIN;
|
||||||
@ -121,9 +123,196 @@ FROM prevstats AS pr;
|
|||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
|
----
|
||||||
|
-- Basic tests for track_functions
|
||||||
|
---
|
||||||
|
CREATE FUNCTION stats_test_func1() RETURNS VOID LANGUAGE plpgsql AS $$BEGIN END;$$;
|
||||||
|
SELECT 'stats_test_func1()'::regprocedure::oid AS stats_test_func1_oid \gset
|
||||||
|
CREATE FUNCTION stats_test_func2() RETURNS VOID LANGUAGE plpgsql AS $$BEGIN END;$$;
|
||||||
|
SELECT 'stats_test_func2()'::regprocedure::oid AS stats_test_func2_oid \gset
|
||||||
|
|
||||||
|
-- test that stats are accumulated
|
||||||
|
BEGIN;
|
||||||
|
SET LOCAL stats_fetch_consistency = none;
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func1_oid);
|
||||||
|
SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid);
|
||||||
|
SELECT stats_test_func1();
|
||||||
|
SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid);
|
||||||
|
SELECT stats_test_func1();
|
||||||
|
SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid);
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func1_oid);
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
-- Verify that function stats are not transactional
|
||||||
|
|
||||||
|
-- rolled back savepoint in committing transaction
|
||||||
|
BEGIN;
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
SAVEPOINT foo;
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
ROLLBACK TO SAVEPOINT foo;
|
||||||
|
SELECT pg_stat_get_xact_function_calls(:stats_test_func2_oid);
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
-- rolled back transaction
|
||||||
|
BEGIN;
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
ROLLBACK;
|
||||||
|
|
||||||
|
SELECT pg_stat_force_next_flush();
|
||||||
|
|
||||||
|
-- check collected stats
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid;
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func2_oid;
|
||||||
|
|
||||||
|
|
||||||
|
-- check that a rolled back drop function stats leaves stats alive
|
||||||
|
BEGIN;
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid;
|
||||||
|
DROP FUNCTION stats_test_func1();
|
||||||
|
-- shouldn't be visible via view
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid;
|
||||||
|
-- but still via oid access
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func1_oid);
|
||||||
|
ROLLBACK;
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid;
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func1_oid);
|
||||||
|
|
||||||
|
|
||||||
|
-- check that function dropped in main transaction leaves no stats behind
|
||||||
|
BEGIN;
|
||||||
|
DROP FUNCTION stats_test_func1();
|
||||||
|
COMMIT;
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid;
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func1_oid);
|
||||||
|
|
||||||
|
-- check that function dropped in a subtransaction leaves no stats behind
|
||||||
|
BEGIN;
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
SAVEPOINT a;
|
||||||
|
SELECT stats_test_func2();
|
||||||
|
SAVEPOINT b;
|
||||||
|
DROP FUNCTION stats_test_func2();
|
||||||
|
COMMIT;
|
||||||
|
SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func2_oid;
|
||||||
|
SELECT pg_stat_get_function_calls(:stats_test_func2_oid);
|
||||||
|
|
||||||
|
|
||||||
|
-- Check that stats for relations are dropped. For that we need to access stats
|
||||||
|
-- by oid after the DROP TABLE. Save oids.
|
||||||
|
CREATE TABLE drop_stats_test();
|
||||||
|
INSERT INTO drop_stats_test DEFAULT VALUES;
|
||||||
|
SELECT 'drop_stats_test'::regclass::oid AS drop_stats_test_oid \gset
|
||||||
|
|
||||||
|
CREATE TABLE drop_stats_test_xact();
|
||||||
|
INSERT INTO drop_stats_test_xact DEFAULT VALUES;
|
||||||
|
SELECT 'drop_stats_test_xact'::regclass::oid AS drop_stats_test_xact_oid \gset
|
||||||
|
|
||||||
|
CREATE TABLE drop_stats_test_subxact();
|
||||||
|
INSERT INTO drop_stats_test_subxact DEFAULT VALUES;
|
||||||
|
SELECT 'drop_stats_test_subxact'::regclass::oid AS drop_stats_test_subxact_oid \gset
|
||||||
|
|
||||||
|
SELECT pg_stat_force_next_flush();
|
||||||
|
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
|
||||||
|
DROP TABLE drop_stats_test;
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_oid);
|
||||||
|
|
||||||
|
-- check that rollback protects against having stats dropped and that local
|
||||||
|
-- modifications don't pose a problem
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
|
||||||
|
SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO drop_stats_test_xact DEFAULT VALUES;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
DROP TABLE drop_stats_test_xact;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
ROLLBACK;
|
||||||
|
SELECT pg_stat_force_next_flush();
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
|
||||||
|
SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
|
||||||
|
-- transactional drop
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
|
||||||
|
SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO drop_stats_test_xact DEFAULT VALUES;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
DROP TABLE drop_stats_test_xact;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
COMMIT;
|
||||||
|
SELECT pg_stat_force_next_flush();
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
|
||||||
|
SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
|
||||||
|
|
||||||
|
-- savepoint rollback (2 levels)
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO drop_stats_test_subxact DEFAULT VALUES;
|
||||||
|
SAVEPOINT sp1;
|
||||||
|
INSERT INTO drop_stats_test_subxact DEFAULT VALUES;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_subxact_oid);
|
||||||
|
SAVEPOINT sp2;
|
||||||
|
DROP TABLE drop_stats_test_subxact;
|
||||||
|
ROLLBACK TO SAVEPOINT sp2;
|
||||||
|
SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_subxact_oid);
|
||||||
|
COMMIT;
|
||||||
|
SELECT pg_stat_force_next_flush();
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
|
||||||
|
-- savepoint rolback (1 level)
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
BEGIN;
|
||||||
|
SAVEPOINT sp1;
|
||||||
|
DROP TABLE drop_stats_test_subxact;
|
||||||
|
SAVEPOINT sp2;
|
||||||
|
ROLLBACK TO SAVEPOINT sp1;
|
||||||
|
COMMIT;
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
|
||||||
|
-- and now actually drop
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
BEGIN;
|
||||||
|
SAVEPOINT sp1;
|
||||||
|
DROP TABLE drop_stats_test_subxact;
|
||||||
|
SAVEPOINT sp2;
|
||||||
|
RELEASE SAVEPOINT sp1;
|
||||||
|
COMMIT;
|
||||||
|
SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
|
||||||
|
|
||||||
DROP TABLE trunc_stats_test, trunc_stats_test1, trunc_stats_test2, trunc_stats_test3, trunc_stats_test4;
|
DROP TABLE trunc_stats_test, trunc_stats_test1, trunc_stats_test2, trunc_stats_test3, trunc_stats_test4;
|
||||||
DROP TABLE prevstats;
|
DROP TABLE prevstats;
|
||||||
|
|
||||||
|
----
|
||||||
|
-- pg_stat_get_snapshot_timestamp behavior
|
||||||
|
----
|
||||||
|
BEGIN;
|
||||||
|
SET LOCAL stats_fetch_consistency = snapshot;
|
||||||
|
-- no snapshot yet, return NULL
|
||||||
|
SELECT pg_stat_get_snapshot_timestamp();
|
||||||
|
-- any attempt at accessing stats will build snapshot
|
||||||
|
SELECT pg_stat_get_function_calls(0);
|
||||||
|
SELECT pg_stat_get_snapshot_timestamp() >= NOW();
|
||||||
|
-- shows NULL again after clearing
|
||||||
|
SELECT pg_stat_clear_snapshot();
|
||||||
|
SELECT pg_stat_get_snapshot_timestamp();
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
----
|
||||||
|
-- pg_stat_have_stats behavior
|
||||||
|
----
|
||||||
|
-- fixed-numbered stats exist
|
||||||
|
SELECT pg_stat_have_stats('bgwriter', 0, 0);
|
||||||
|
-- unknown stats kinds error out
|
||||||
|
SELECT pg_stat_have_stats('zaphod', 0, 0);
|
||||||
|
-- db stats have objoid 0
|
||||||
|
SELECT pg_stat_have_stats('database', (SELECT oid FROM pg_database WHERE datname = current_database()), 1);
|
||||||
|
SELECT pg_stat_have_stats('database', (SELECT oid FROM pg_database WHERE datname = current_database()), 0);
|
||||||
|
|
||||||
|
|
||||||
-- ensure that stats accessors handle NULL input correctly
|
-- ensure that stats accessors handle NULL input correctly
|
||||||
SELECT pg_stat_get_replication_slot(NULL);
|
SELECT pg_stat_get_replication_slot(NULL);
|
||||||
SELECT pg_stat_get_subscription_stats(NULL);
|
SELECT pg_stat_get_subscription_stats(NULL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user