From e49626862d19300412ee4bdcec8d7bac65ebd4b4 Mon Sep 17 00:00:00 2001 From: Rafia Sabih Date: Fri, 20 Dec 2024 17:07:52 +0100 Subject: [PATCH] Handle compatibility issues (#15) * Fix for changed definition of GetDatum for PG versions over 15 * Remove tuplestore_donestoring for PG versions over 15 * Add github tests for versions 15, 16, and 17 * Changes in sql file and a new expected file is added to accommodate changed behaviour of pg_stat_statements_reset function --- .github/workflows/tests.yaml | 20 +- LICENSE | 2 +- expected/pg_mon_1.out | 371 +++++++++++++++++++++++++++++++++++ pg_mon.c | 186 ++++++++++++------ sql/pg_mon.sql | 20 +- 5 files changed, 524 insertions(+), 75 deletions(-) create mode 100644 expected/pg_mon_1.out diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index d7cdd45..7037ace 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -8,7 +8,7 @@ on: jobs: tests: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 env: PG: ${{ matrix.postgres-version }} strategy: @@ -19,18 +19,26 @@ jobs: - '12' - '13' - '14' - + - '15' + - '16' + - '17' + steps: - uses: actions/checkout@v2 - name: Set up packages run: | set -e + # add the official Ubuntu/Debian APT repository for PostgreSQL sudo sh -c "echo \"deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main $PG\" > /etc/apt/sources.list.d/pgdg.list" + curl -Ls https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - sudo apt-get update - sudo apt-get install -yq --no-install-suggests --no-install-recommends curl postgresql-common lcov libevent-dev pv brotli libbrotli1 libbrotli-dev - # forbid creation of a main cluster when package is installed + + sudo apt-get install --assume-yes --quiet --no-install-suggests --no-install-recommends curl postgresql-common lcov libkrb5-dev + + # forbid creation of a "main" cluster when a new postgresql-x.y server package is installed sudo sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf - sudo apt-get install -yq --no-install-suggests --no-install-recommends postgresql-$PG postgresql-server-dev-$PG + + sudo apt-get --assume-yes --quiet --no-install-suggests --no-install-recommends install postgresql-$PG postgresql-server-dev-$PG - name: Download noisia run: | VERSION=0.1.0 @@ -58,7 +66,7 @@ jobs: finish: needs: tests - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - name: Coveralls Finished uses: coverallsapp/github-action@master diff --git a/LICENSE b/LICENSE index aa0d088..68badc2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Rafia Sabih +Copyright (c) 2024 Rafia Sabih Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/expected/pg_mon_1.out b/expected/pg_mon_1.out new file mode 100644 index 0000000..81fe9cb --- /dev/null +++ b/expected/pg_mon_1.out @@ -0,0 +1,371 @@ +set pg_mon.log_new_query = false; +create extension pg_mon; +create extension pg_stat_statements; +create table t (i int, j text); +create table t2 (i int, j text); +insert into t values (generate_series(1,10), repeat('test_pg_mon', 10)); +insert into t2 values (generate_series(1,10), repeat('test_pg_mon', 10)); +analyze t; +analyze t2; +-- Test log_new_query flag +set pg_mon.log_new_query = true; +select count(*) from t; + count +------- + 10 +(1 row) + +create role check_pg_mon_logging; +alter role check_pg_mon_logging with password 'donotlogme'; +drop role check_pg_mon_logging; +set pg_mon.log_new_query = false; +-- Seq scan query output +select pg_mon_reset(); + pg_mon_reset +-------------- + +(1 row) + +select pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +select * from t; + i | j +----+---------------------------------------------------------------------------------------------------------------- + 1 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 2 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 3 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 4 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 5 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 6 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 7 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 8 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 9 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 10 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon +(10 rows) + +select expected_rows, actual_rows, seq_scans, hist_time_ubounds, hist_time_freq from pg_mon where seq_scans IS NOT NULL; + expected_rows | actual_rows | seq_scans | hist_time_ubounds | hist_time_freq +---------------+-------------+-----------+-------------------+---------------- + 10 | 10 | {t} | {1} | {1} +(1 row) + +create index on t(i); +analyze t; +set random_page_cost = 0; +--Index scan output +select pg_mon_reset(); + pg_mon_reset +-------------- + +(1 row) + +select pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +select * from t where i < 5; + i | j +---+---------------------------------------------------------------------------------------------------------------- + 1 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 2 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 3 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 4 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon +(4 rows) + +select expected_rows, actual_rows, seq_scans, index_scans, hist_time_ubounds, hist_time_freq from pg_mon where index_scans IS NOT NULL; + expected_rows | actual_rows | seq_scans | index_scans | hist_time_ubounds | hist_time_freq +---------------+-------------+-----------+-------------+-------------------+---------------- + 3 | 4 | | {t_i_idx} | {1} | {1} +(1 row) + +--When query changes scan method +set enable_indexscan = 'off'; +select * from t where i < 5; + i | j +---+---------------------------------------------------------------------------------------------------------------- + 1 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 2 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 3 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 4 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon +(4 rows) + +select expected_rows, actual_rows, index_scans, bitmap_scans, hist_time_ubounds, hist_time_freq from pg_mon where index_scans IS NOT NULL and bitmap_scans IS NOT NULL; + expected_rows | actual_rows | index_scans | bitmap_scans | hist_time_ubounds | hist_time_freq +---------------+-------------+-------------+--------------+-------------------+---------------- + 3 | 4 | {t_i_idx} | {t_i_idx} | {1} | {2} +(1 row) + +set enable_bitmapscan = 'off'; +select * from t where i < 5; + i | j +---+---------------------------------------------------------------------------------------------------------------- + 1 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 2 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 3 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 4 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon +(4 rows) + +select expected_rows, actual_rows, seq_scans, index_scans, bitmap_scans, hist_time_ubounds, hist_time_freq from pg_mon where seq_scans IS NOT NULL and index_scans IS NOT NULL; + expected_rows | actual_rows | seq_scans | index_scans | bitmap_scans | hist_time_ubounds | hist_time_freq +---------------+-------------+-----------+-------------+--------------+-------------------+---------------- + 3 | 4 | {t} | {t_i_idx} | {t_i_idx} | {1} | {3} +(1 row) + +--Scan information for update statements +set enable_indexscan = 'on'; +set enable_bitmapscan = 'on'; +update t set i = 11 where i = 1; +select seq_scans, index_scans, update_query from pg_mon where update_query = true; + seq_scans | index_scans | update_query +-----------+-------------+-------------- + {} | {t_i_idx} | t +(1 row) + +select pg_mon_reset(); + pg_mon_reset +-------------- + +(1 row) + +select pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +set enable_indexscan = 'off'; +set enable_bitmapscan = 'off'; +update t set i = 1; +select seq_scans, index_scans, update_query from pg_mon where update_query = true; + seq_scans | index_scans | update_query +-----------+-------------+-------------- + {t} | {} | t +(1 row) + +--Scan information for delete statements +select pg_mon_reset(); + pg_mon_reset +-------------- + +(1 row) + +select pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +set enable_indexscan = 'on'; +set enable_bitmapscan = 'on'; +delete from t where i < 5; +select seq_scans, index_scans, update_query from pg_mon where update_query = true; + seq_scans | index_scans | update_query +-----------+-------------+-------------- + {} | {t_i_idx} | t +(1 row) + +select pg_mon_reset(); + pg_mon_reset +-------------- + +(1 row) + +select pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +set enable_indexscan = 'off'; +set enable_bitmapscan = 'off'; +delete from t; +select seq_scans, index_scans, update_query from pg_mon where update_query = true; + seq_scans | index_scans | update_query +-----------+-------------+-------------- + {t} | {} | t +(1 row) + +insert into t values (generate_series(1,10), repeat('bsdshkjd3h', 10)); +--Join output +select pg_mon_reset(); + pg_mon_reset +-------------- + +(1 row) + +select pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +select * from t, t2 where t.i = t2.i; + i | j | i | j +----+------------------------------------------------------------------------------------------------------+----+---------------------------------------------------------------------------------------------------------------- + 1 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 1 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 2 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 2 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 3 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 3 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 4 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 4 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 5 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 5 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 6 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 6 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 7 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 7 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 8 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 8 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 9 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 9 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 10 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 10 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon +(10 rows) + +select expected_rows, actual_rows, seq_scans, index_scans, hash_join_count, hist_time_ubounds, hist_time_freq from pg_mon where hash_join_count > 0; + expected_rows | actual_rows | seq_scans | index_scans | hash_join_count | hist_time_ubounds | hist_time_freq +---------------+-------------+-----------+-------------+-----------------+-------------------+---------------- + 10 | 10 | {t,t2} | | 1 | {1} | {1} +(1 row) + +set enable_hashjoin = 'off'; +select pg_mon_reset(); + pg_mon_reset +-------------- + +(1 row) + +select pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +select * from t, t2 where t.i = t2.i; + i | j | i | j +----+------------------------------------------------------------------------------------------------------+----+---------------------------------------------------------------------------------------------------------------- + 1 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 1 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 2 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 2 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 3 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 3 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 4 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 4 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 5 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 5 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 6 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 6 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 7 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 7 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 8 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 8 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 9 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 9 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 10 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 10 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon +(10 rows) + +select expected_rows, actual_rows, seq_scans, index_scans, merge_join_count, hist_time_ubounds, hist_time_freq from pg_mon where merge_join_count > 0; + expected_rows | actual_rows | seq_scans | index_scans | merge_join_count | hist_time_ubounds | hist_time_freq +---------------+-------------+-----------+-------------+------------------+-------------------+---------------- + 10 | 10 | {t,t2} | | 1 | {1} | {1} +(1 row) + +set enable_mergejoin = 'off'; +select pg_mon_reset(); + pg_mon_reset +-------------- + +(1 row) + +select pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +select * from t, t2 where t.i = t2.i; + i | j | i | j +----+------------------------------------------------------------------------------------------------------+----+---------------------------------------------------------------------------------------------------------------- + 1 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 1 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 2 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 2 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 3 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 3 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 4 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 4 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 5 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 5 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 6 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 6 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 7 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 7 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 8 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 8 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 9 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 9 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 10 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 10 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon +(10 rows) + +select expected_rows, actual_rows, seq_scans, index_scans, nested_loop_join_count, hist_time_ubounds, hist_time_freq from pg_mon where nested_loop_join_count > 0; + expected_rows | actual_rows | seq_scans | index_scans | nested_loop_join_count | hist_time_ubounds | hist_time_freq +---------------+-------------+-----------+-------------+------------------------+-------------------+---------------- + 10 | 10 | {t,t2} | | 1 | {1} | {1} +(1 row) + +-- Get plan information right after planning phase +set pg_mon.plan_info_immediate = 'true'; +select pg_mon_reset(); + pg_mon_reset +-------------- + +(1 row) + +select pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +select * from t, t2 where t.i = t2.i; + i | j | i | j +----+------------------------------------------------------------------------------------------------------+----+---------------------------------------------------------------------------------------------------------------- + 1 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 1 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 2 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 2 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 3 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 3 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 4 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 4 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 5 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 5 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 6 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 6 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 7 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 7 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 8 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 8 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 9 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 9 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 10 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 10 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon +(10 rows) + +select expected_rows, actual_rows, seq_scans, index_scans, nested_loop_join_count, hist_time_ubounds, hist_time_freq from pg_mon where nested_loop_join_count > 0; + expected_rows | actual_rows | seq_scans | index_scans | nested_loop_join_count | hist_time_ubounds | hist_time_freq +---------------+-------------+-----------+-------------+------------------------+-------------------+---------------- + 10 | 10 | {t,t2} | | 1 | {1} | {1} +(1 row) + +-- Cover the path for skipping plan time information +set pg_mon.plan_info_disable = 'true'; +select pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +select pg_mon_reset(); + pg_mon_reset +-------------- + +(1 row) + +select * from t, t2 where t.i = t2.i; + i | j | i | j +----+------------------------------------------------------------------------------------------------------+----+---------------------------------------------------------------------------------------------------------------- + 1 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 1 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 2 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 2 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 3 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 3 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 4 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 4 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 5 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 5 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 6 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 6 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 7 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 7 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 8 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 8 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 9 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 9 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon + 10 | bsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3hbsdshkjd3h | 10 | test_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_montest_pg_mon +(10 rows) + +select expected_rows, actual_rows, seq_scans, index_scans, nested_loop_join_count, hist_time_ubounds, hist_time_freq from pg_mon where expected_rows = 0 and actual_rows = 10; + expected_rows | actual_rows | seq_scans | index_scans | nested_loop_join_count | hist_time_ubounds | hist_time_freq +---------------+-------------+-----------+-------------+------------------------+-------------------+---------------- + 0 | 10 | | | 0 | {1} | {1} +(1 row) + +--Cleanup +drop table t; +drop table t2; +drop extension pg_stat_statements; +drop extension pg_mon; diff --git a/pg_mon.c b/pg_mon.c index 7940140..741dd1c 100644 --- a/pg_mon.c +++ b/pg_mon.c @@ -40,7 +40,6 @@ #include "tcop/utility.h" - Datum pg_mon(PG_FUNCTION_ARGS); Datum pg_mon_reset(PG_FUNCTION_ARGS); @@ -92,10 +91,12 @@ typedef struct mon_rec static int nesting_level = 0; extern void _PG_init(void); +#if PG_VERSION_NUM < 150000 extern void _PG_fini(void); +#endif /* LWlock to mange the reading and writing the hash table. */ -LWLock *mon_lock; +static LWLock *mon_lock; typedef enum AddHist{ QUERY_TIME, @@ -109,14 +110,39 @@ static ExecutorRun_hook_type prev_ExecutorRun = NULL; static ExecutorFinish_hook_type prev_ExecutorFinish = NULL; static ExecutorEnd_hook_type prev_ExecutorEnd = NULL; static ProcessUtility_hook_type prev_ProcessUtility = NULL; - static void pgmon_ExecutorStart(QueryDesc *queryDesc, int eflags); -static void pgmon_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, - uint64 count, bool execute_once); + +#if PG_VERSION_NUM < 180000 +static void ER_hook(QueryDesc *queryDesc, ScanDirection direction,\ + uint64 count, bool execute_once); +#define _ER_hook \ + static void ER_hook(QueryDesc *queryDesc, ScanDirection direction,\ + uint64 count, bool execute_once) +#define _prev_ER_hook \ + prev_ExecutorRun(queryDesc, direction,\ + count, execute_once) +#define _standard_ExecutorRun \ + standard_ExecutorRun(queryDesc, direction,\ + count, execute_once) +#else +static void ER_hook(QueryDesc *queryDesc, ScanDirection direction, + uint64 count); +#define _ER_hook \ + static void ER_hook(QueryDesc *queryDesc, ScanDirection direction,\ + uint64 count) +#define _prev_ER_hook \ + prev_ExecutorRun(queryDesc, direction,\ + count) +#define _standard_ExecutorRun \ + standard_ExecutorRun(queryDesc, direction,\ + count) +#endif + static void pgmon_ExecutorFinish(QueryDesc *queryDesc); static void pgmon_ExecutorEnd(QueryDesc *queryDesc); static void pgmon_plan_store(QueryDesc *queryDesc); static void pgmon_exec_store(QueryDesc *queryDesc); + #if PG_VERSION_NUM < 130000 static void PU_hook(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, @@ -162,8 +188,13 @@ static void PU_hook(PlannedStmt *pstmt, const char *queryString, #define _standard_ProcessUtility \ standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc) #endif +#if (PG_VERSION_NUM >= 150000) +static shmem_request_hook_type prev_shmem_request_hook = NULL; +static void ourextension_shmem_request(void); +#endif /* Saved hook values in case of unload */ static shmem_startup_hook_type prev_shmem_startup_hook = NULL; +static void shmem_startup(void); static void shmem_shutdown(int code, Datum arg); static void plan_tree_traversal(QueryDesc *query, Plan *plan, mon_rec *entry); @@ -195,46 +226,6 @@ static int64 row_bucket_bounds[ROWNUMBUCKETS] = { * current query */ static mon_rec temp_entry; -/* - * shmem_startup hook: allocate and attach to shared memory, - */ -static void -shmem_startup(void) -{ - HASHCTL info; - - if (prev_shmem_startup_hook) - prev_shmem_startup_hook(); - - mon_ht = NULL; - - /* - * Create or attach to the shared memory state, including hash table - */ - LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); - - memset(&info, 0, sizeof(info)); - info.keysize = sizeof(uint32); - info.entrysize = sizeof(mon_rec); -#if PG_VERSION_NUM > 100000 - info.hash = uint32_hash; - - mon_ht = ShmemInitHash("mon_hash", MON_HT_SIZE, MON_HT_SIZE, - &info, HASH_ELEM | HASH_FUNCTION); -#else - mon_ht = ShmemInitHash("mon_hash", MON_HT_SIZE, MON_HT_SIZE, - &info, HASH_ELEM); -#endif - mon_lock = &(GetNamedLWLockTranche("mon_lock"))->lock; - LWLockRelease(AddinShmemInitLock); - - /* - * If we're in the postmaster (or a standalone backend...), set up a shmem - * exit hook to dump the statistics to disk. - */ - if (!IsUnderPostmaster) - on_shmem_exit(shmem_shutdown, (Datum) 0); -} /* * shmem_shutdown hook @@ -259,7 +250,6 @@ qmon_memsize(void) return hash_estimate_size(MON_HT_SIZE, sizeof(mon_rec)); } - /* * Module Load Callback */ @@ -316,16 +306,20 @@ _PG_init(void) * the postmaster process.) We'll allocate or attach to the shared * resources in *_shmem_startup(). */ - RequestAddinShmemSpace(qmon_memsize()); - RequestNamedLWLockTranche("mon_lock", 1); - +#if (PG_VERSION_NUM >= 150000) + prev_shmem_request_hook = shmem_request_hook; + shmem_request_hook = ourextension_shmem_request; +#else + RequestAddinShmemSpace(qmon_memsize()); + RequestNamedLWLockTranche("mon_lock", 1); +#endif /* Install Hooks */ prev_shmem_startup_hook = shmem_startup_hook; shmem_startup_hook = shmem_startup; prev_ExecutorStart = ExecutorStart_hook; ExecutorStart_hook = pgmon_ExecutorStart; prev_ExecutorRun = ExecutorRun_hook; - ExecutorRun_hook = pgmon_ExecutorRun; + ExecutorRun_hook = ER_hook; prev_ExecutorFinish = ExecutorFinish_hook; ExecutorFinish_hook = pgmon_ExecutorFinish; prev_ExecutorEnd = ExecutorEnd_hook; @@ -334,9 +328,24 @@ _PG_init(void) ProcessUtility_hook = PU_hook; } +#if (PG_VERSION_NUM >= 150000) +/* + * Requests any additional shared memory required for our extension + */ +static void +ourextension_shmem_request(void) +{ + if (prev_shmem_request_hook) + prev_shmem_request_hook(); + + RequestAddinShmemSpace(qmon_memsize()); + RequestNamedLWLockTranche("mon_lock", 1); +} +#endif /* * Module unload callback */ +#if PG_VERSION_NUM < 150000 void _PG_fini(void) { @@ -348,7 +357,40 @@ _PG_fini(void) ExecutorEnd_hook = prev_ExecutorEnd; ProcessUtility_hook = prev_ProcessUtility; } +#endif +/* + * shmem_startup hook: allocate and attach to shared memory, + */ +static void +shmem_startup(void) +{ + HASHCTL info; + + if (prev_shmem_startup_hook) + prev_shmem_startup_hook(); + mon_ht = NULL; + + /* + * Create or attach to the shared memory state, including hash table + */ + LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); + + memset(&info, 0, sizeof(info)); + info.keysize = sizeof(uint64); + info.entrysize = sizeof(mon_rec); + mon_ht = ShmemInitHash("mon_hash", MON_HT_SIZE, MON_HT_SIZE, + &info, HASH_ELEM | HASH_BLOBS); + mon_lock = &(GetNamedLWLockTranche("mon_lock"))->lock; + LWLockRelease(AddinShmemInitLock); + + /* + * If we're in the postmaster (or a standalone backend...), set up a shmem + * exit hook to dump the statistics to disk. + */ + if (!IsUnderPostmaster) + on_shmem_exit(shmem_shutdown, (Datum) 0); +} /* * ExecutorStart hook: start up logging if needed @@ -423,17 +465,20 @@ pgmon_ExecutorStart(QueryDesc *queryDesc, int eflags) /* * ExecutorRun hook: all we need do is track nesting depth */ -static void -pgmon_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, - uint64 count, bool execute_once) +_ER_hook { nesting_level++; PG_TRY(); { if (prev_ExecutorRun) - prev_ExecutorRun(queryDesc, direction, count, execute_once); + { + _prev_ER_hook; + } else - standard_ExecutorRun(queryDesc, direction, count, execute_once); + { + _standard_ExecutorRun; + } + #if PG_VERSION_NUM < 130000 nesting_level--; #endif @@ -903,8 +948,8 @@ pg_mon(PG_FUNCTION_ARGS) Datum *rownumdatums = (Datum *) palloc(ROWNUMBUCKETS * sizeof(Datum)); Datum values[MON_COLS]; bool nulls[MON_COLS] = {0}; - int i = 0, n, idx = 0, last_fill_bucket = 0; - ArrayType *arry = NULL; + int i = 0, last_fill_bucket = 0, n = 0, idx = 0; + ArrayType *arry; memset(values, 0, sizeof(values)); memset(nulls, 0, sizeof(nulls)); @@ -925,8 +970,16 @@ pg_mon(PG_FUNCTION_ARGS) ArrayType *arry; int n = 0, idx = 0; for (n = 0; n < MAX_TABLES && entry->seq_scans[n] != 0; n++) + { +#if PG_VERSION_NUM < 160000 datums[idx++] = ObjectIdGetDatum(&entry->seq_scans[n]); + } arry = construct_array(datums, idx, OIDOID, sizeof(Oid), false, 'i'); +#else + datums[idx++] = ObjectIdGetDatum(*(Oid *)&entry->seq_scans[n]); + } + arry = construct_array(datums, idx, OIDOID, sizeof(Oid), true, 'i'); +#endif values[i++] = PointerGetDatum(arry); } if (!entry->ModifyTable && entry->index_scans[0] == 0) @@ -937,8 +990,16 @@ pg_mon(PG_FUNCTION_ARGS) ArrayType *arry; int n = 0, idx = 0; for (n = 0; n < MAX_TABLES && entry->index_scans[n] != 0; n++) + { +#if PG_VERSION_NUM < 160000 datums[idx++] = ObjectIdGetDatum(&entry->index_scans[n]); + } arry = construct_array(datums, idx, OIDOID, sizeof(Oid), false, 'i'); +#else + datums[idx++] = ObjectIdGetDatum(*(Oid *)&entry->index_scans[n]); + } + arry = construct_array(datums, idx, OIDOID, sizeof(Oid), true, 'i'); +#endif values[i++] = PointerGetDatum(arry); } if (!entry->ModifyTable && entry->bitmap_scans[0] == 0) @@ -949,8 +1010,16 @@ pg_mon(PG_FUNCTION_ARGS) ArrayType *arry; int n = 0, idx = 0; for (n = 0; n < MAX_TABLES && entry->bitmap_scans[n] != 0; n++) + { +#if PG_VERSION_NUM < 160000 datums[idx++] = ObjectIdGetDatum(&entry->bitmap_scans[n]); + } arry = construct_array(datums, idx, OIDOID, sizeof(Oid), false, 'i'); +#else + datums[idx++] = ObjectIdGetDatum(*(Oid *)&entry->bitmap_scans[n]); + } + arry = construct_array(datums, idx, OIDOID, sizeof(Oid), true, 'i'); +#endif values[i++] = PointerGetDatum(arry); } values[i++] = NameGetDatum(&entry->other_scan); @@ -1034,9 +1103,10 @@ pg_mon(PG_FUNCTION_ARGS) LWLockRelease(mon_lock); +#if PG_VERSION_NUM < 150000 /* clean up and return the tuplestore */ tuplestore_donestoring(tupstore); - +#endif rsinfo->returnMode = SFRM_Materialize; rsinfo->setResult = tupstore; rsinfo->setDesc = tupdesc; diff --git a/sql/pg_mon.sql b/sql/pg_mon.sql index 255f8b8..4b490c0 100644 --- a/sql/pg_mon.sql +++ b/sql/pg_mon.sql @@ -19,7 +19,7 @@ set pg_mon.log_new_query = false; -- Seq scan query output select pg_mon_reset(); -select pg_stat_statements_reset(); +select pg_stat_statements_reset() IS NOT NULL AS t; select * from t; select expected_rows, actual_rows, seq_scans, hist_time_ubounds, hist_time_freq from pg_mon where seq_scans IS NOT NULL; @@ -29,7 +29,7 @@ set random_page_cost = 0; --Index scan output select pg_mon_reset(); -select pg_stat_statements_reset(); +select pg_stat_statements_reset() IS NOT NULL AS t; select * from t where i < 5; select expected_rows, actual_rows, seq_scans, index_scans, hist_time_ubounds, hist_time_freq from pg_mon where index_scans IS NOT NULL; @@ -48,7 +48,7 @@ set enable_bitmapscan = 'on'; update t set i = 11 where i = 1; select seq_scans, index_scans, update_query from pg_mon where update_query = true; select pg_mon_reset(); -select pg_stat_statements_reset(); +select pg_stat_statements_reset() IS NOT NULL AS t; set enable_indexscan = 'off'; set enable_bitmapscan = 'off'; @@ -57,13 +57,13 @@ select seq_scans, index_scans, update_query from pg_mon where update_query = tru --Scan information for delete statements select pg_mon_reset(); -select pg_stat_statements_reset(); +select pg_stat_statements_reset() IS NOT NULL AS t; set enable_indexscan = 'on'; set enable_bitmapscan = 'on'; delete from t where i < 5; select seq_scans, index_scans, update_query from pg_mon where update_query = true; select pg_mon_reset(); -select pg_stat_statements_reset(); +select pg_stat_statements_reset() IS NOT NULL AS t; set enable_indexscan = 'off'; set enable_bitmapscan = 'off'; @@ -73,32 +73,32 @@ insert into t values (generate_series(1,10), repeat('bsdshkjd3h', 10)); --Join output select pg_mon_reset(); -select pg_stat_statements_reset(); +select pg_stat_statements_reset() IS NOT NULL AS t; select * from t, t2 where t.i = t2.i; select expected_rows, actual_rows, seq_scans, index_scans, hash_join_count, hist_time_ubounds, hist_time_freq from pg_mon where hash_join_count > 0; set enable_hashjoin = 'off'; select pg_mon_reset(); -select pg_stat_statements_reset(); +select pg_stat_statements_reset() IS NOT NULL AS t; select * from t, t2 where t.i = t2.i; select expected_rows, actual_rows, seq_scans, index_scans, merge_join_count, hist_time_ubounds, hist_time_freq from pg_mon where merge_join_count > 0; set enable_mergejoin = 'off'; select pg_mon_reset(); -select pg_stat_statements_reset(); +select pg_stat_statements_reset() IS NOT NULL AS t; select * from t, t2 where t.i = t2.i; select expected_rows, actual_rows, seq_scans, index_scans, nested_loop_join_count, hist_time_ubounds, hist_time_freq from pg_mon where nested_loop_join_count > 0; -- Get plan information right after planning phase set pg_mon.plan_info_immediate = 'true'; select pg_mon_reset(); -select pg_stat_statements_reset(); +select pg_stat_statements_reset() IS NOT NULL AS t; select * from t, t2 where t.i = t2.i; select expected_rows, actual_rows, seq_scans, index_scans, nested_loop_join_count, hist_time_ubounds, hist_time_freq from pg_mon where nested_loop_join_count > 0; -- Cover the path for skipping plan time information set pg_mon.plan_info_disable = 'true'; -select pg_stat_statements_reset(); +select pg_stat_statements_reset() IS NOT NULL AS t; select pg_mon_reset(); select * from t, t2 where t.i = t2.i; select expected_rows, actual_rows, seq_scans, index_scans, nested_loop_join_count, hist_time_ubounds, hist_time_freq from pg_mon where expected_rows = 0 and actual_rows = 10;