[PG-810] PG-17 Support (#463)
* Temporary disable all workflows * Add build workflow with PG17 * Fix incompatibilities * Fix 007_settings_pgsm_query_shared_buffer.pl test * Fix 018_column_names.pl * Fix 025_compare_pgss.pl * Remove tuplestore_donestoring usage at all * Rename I/O timing statistics columns to shared_blk_{read|write}_time * Fix comments with fileds numbers * Fix format * Revert "Temporary disable all workflows" This reverts commitpull/476/head12e75beb63
. * Disable all workflows except check and build for PG 15, 16 and 17 * Fix * Fix comments * Fix migration * Use REL_17_BETA1 in CI * Add timers tests to 028_temp_block.pl * Add local blocks timing statistics columns local_blk_{write|read}_time * Fix t/027_local_blocks.pl test for older PG versions * Fix * Add jit_deform_{count|time} metrics * Fix * Add stats_since and minmax_stats_since fields * Revert "Disable all workflows except check and build for PG 15, 16 and 17" This reverts commit73febf3aee
. * Fix t/028_temp_block.pl for PG14 and below * Fix build for PG12 * Add pgdg workflow for PG17 * Try to fix PG pgdg workflow * Fixes and formatting * Format code * Add level tracking regression test * Fix nesting level tracking * Format code * Add level tracking test expected result for PG13 * Fix for PG12 * Skip level tracking regression test for PG version less than 14 * Fix toplevel calculation for older PG version * Fix level tracking test results * Fix nesting level counting for older PG version * Revert "Fix nesting level counting for older PG version" This reverts commit3e91da8010
. * Fix level tracking for older PG versions once again * Set REL_17_BETA2 tag for PG * Add CI badge for PG17 * Use PG17 for examples in readme
parent
c796995e0c
commit
dacb41f9e4
|
@ -0,0 +1,147 @@
|
|||
name: postgresql-17-build
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg-17-build-test
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Clone postgres repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: 'postgres/postgres'
|
||||
ref: 'REL_17_BETA2' # TODO: Replace with REL_17_STABLE
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt purge postgresql-client-common postgresql-common \
|
||||
postgresql postgresql*
|
||||
sudo apt-get install -y libreadline6-dev systemtap-sdt-dev \
|
||||
zlib1g-dev libssl-dev libpam0g-dev bison flex \
|
||||
libipc-run-perl -y docbook-xsl docbook-xsl libxml2 libxml2-utils \
|
||||
libxml2-dev libxslt-dev xsltproc libkrb5-dev libldap2-dev \
|
||||
libsystemd-dev gettext tcl-dev libperl-dev pkg-config clang-11 \
|
||||
llvm-11 llvm-11-dev libselinux1-dev python3-dev \
|
||||
uuid-dev liblz4-dev
|
||||
sudo rm -rf /var/lib/postgresql /var/log/postgresql /etc/postgresql \
|
||||
/usr/lib/postgresql /usr/include/postgresql /usr/share/postgresql \
|
||||
/etc/postgresql
|
||||
sudo rm -f /usr/bin/pg_config
|
||||
sudo /usr/bin/perl -MCPAN -e 'install IPC::Run'
|
||||
sudo /usr/bin/perl -MCPAN -e 'install Text::Trim'
|
||||
|
||||
- name: Create pgsql dir
|
||||
run: mkdir -p /opt/pgsql
|
||||
|
||||
- name: Build postgres
|
||||
run: |
|
||||
export PATH="/opt/pgsql/bin:$PATH"
|
||||
./configure '--build=x86_64-linux-gnu' '--prefix=/usr' \
|
||||
'--includedir=${prefix}/include' '--mandir=${prefix}/share/man' \
|
||||
'--infodir=${prefix}/share/info' '--sysconfdir=/etc' \
|
||||
'--localstatedir=/var' '--libdir=${prefix}/lib/x86_64-linux-gnu' \
|
||||
'--libexecdir=${prefix}/lib/x86_64-linux-gnu' '--with-icu' \
|
||||
'--with-tcl' '--with-perl' '--with-python' '--with-pam' \
|
||||
'--with-openssl' '--with-libxml' '--with-libxslt' '--with-ldap' \
|
||||
'PYTHON=/usr/bin/python3' '--mandir=/usr/share/postgresql/17/man' \
|
||||
'--docdir=/usr/share/doc/postgresql-doc-17' '--with-pgport=5432' \
|
||||
'--sysconfdir=/etc/postgresql-common' '--datarootdir=/usr/share' \
|
||||
'--datadir=/usr/share/postgresql/17' '--with-uuid=e2fs' \
|
||||
'--bindir=/usr/lib/postgresql/17/bin' '--enable-tap-tests' \
|
||||
'--libdir=/usr/lib/x86_64-linux-gnu' '--enable-debug' \
|
||||
'--libexecdir=/usr/lib/postgresql' '--with-gnu-ld' \
|
||||
'--includedir=/usr/include/postgresql' '--enable-dtrace' \
|
||||
'--enable-nls' '--enable-thread-safety' '--disable-rpath' \
|
||||
'--with-system-tzdata=/usr/share/zoneinfo' '--with-llvm' \
|
||||
'LLVM_CONFIG=/usr/bin/llvm-config-11' 'CLANG=/usr/bin/clang-11' \
|
||||
'--with-systemd' '--with-selinux' 'MKDIR_P=/bin/mkdir -p' \
|
||||
'PROVE=/usr/bin/prove' 'TAR=/bin/tar' 'XSLTPROC=xsltproc --nonet' \
|
||||
'LDFLAGS=-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now' \
|
||||
'build_alias=x86_64-linux-gnu' '--with-gssapi' \
|
||||
'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2' \
|
||||
'CFLAGS=-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer' \
|
||||
'CXXFLAGS=-g -O2 -fstack-protector-strong -Wformat -Werror=format-security'
|
||||
make world
|
||||
sudo make install-world
|
||||
|
||||
- name: Start postgresql cluster
|
||||
run: |
|
||||
export PATH="/usr/lib/postgresql/17/bin:$PATH"
|
||||
sudo cp /usr/lib/postgresql/17/bin/pg_config /usr/bin
|
||||
initdb -D /opt/pgsql/data
|
||||
pg_ctl -D /opt/pgsql/data -l logfile start
|
||||
|
||||
- name: Clone pg_stat_monitor repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: 'src/pg_stat_monitor'
|
||||
|
||||
- name: Build pg_stat_monitor
|
||||
run: |
|
||||
make USE_PGXS=1
|
||||
sudo make USE_PGXS=1 install
|
||||
working-directory: src/pg_stat_monitor
|
||||
|
||||
- name: Configure and Restart Server
|
||||
run: |
|
||||
export PATH="/usr/lib/postgresql/17/bin:$PATH"
|
||||
pg_ctl -D /opt/pgsql/data -l logfile stop
|
||||
echo "shared_preload_libraries = 'pg_stat_monitor'" >> \
|
||||
/opt/pgsql/data/postgresql.conf
|
||||
echo "compute_query_id = regress" >> /opt/pgsql/data/postgresql.conf
|
||||
pg_ctl -D /opt/pgsql/data -l logfile start
|
||||
working-directory: src/pg_stat_monitor
|
||||
|
||||
- name: Start pg_stat_monitor_tests
|
||||
run: |
|
||||
make installcheck
|
||||
working-directory: src/pg_stat_monitor/
|
||||
|
||||
- name: Change dir permissions on fail
|
||||
if: ${{ failure() }}
|
||||
run: |
|
||||
sudo chmod -R ugo+rwx t
|
||||
sudo chmod -R ugo+rwx tmp_check
|
||||
exit 2 # regenerate error so that we can upload files in next step
|
||||
working-directory: src/pg_stat_monitor
|
||||
|
||||
- name: Upload logs on fail
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Regressions diff and postgresql log
|
||||
path: |
|
||||
src/pg_stat_monitor/regression.diffs
|
||||
src/pg_stat_monitor/regression.out
|
||||
src/pg_stat_monitor/logfile
|
||||
src/pg_stat_monitor/t/results/
|
||||
src/pg_stat_monitor/tmp_check/log/
|
||||
!src/pg_stat_monitor/tmp_check/**/archives/*
|
||||
!src/pg_stat_monitor/tmp_check/**/backup/*
|
||||
!src/pg_stat_monitor/tmp_check/**/pgdata/*
|
||||
!src/pg_stat_monitor/tmp_check/**/archives/
|
||||
!src/pg_stat_monitor/tmp_check/**/backup/
|
||||
!src/pg_stat_monitor/tmp_check/**/pgdata/
|
||||
if-no-files-found: warn
|
||||
retention-days: 3
|
||||
|
||||
- name: Start Server installcheck-world tests
|
||||
run: make installcheck-world
|
||||
|
||||
- name: Report on installcheck-world test suites fail
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: Regressions output files of failed testsuite, and pg log
|
||||
path: |
|
||||
**/regression.diffs
|
||||
**/regression.out
|
||||
src/pg_stat_monitor/logfile
|
||||
retention-days: 3
|
|
@ -0,0 +1,93 @@
|
|||
name: postgresql-17-pgdg-package
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg-17-pgdg-package-test
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Clone pg_stat_monitor repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: 'src/pg_stat_monitor'
|
||||
|
||||
- name: Delete old postgresql files
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt purge postgresql-client-common postgresql-common \
|
||||
postgresql postgresql*
|
||||
sudo apt-get install -y libreadline6-dev systemtap-sdt-dev wget \
|
||||
zlib1g-dev libssl-dev libpam0g-dev bison flex libipc-run-perl
|
||||
sudo rm -rf /var/lib/postgresql /var/log/postgresql /etc/postgresql \
|
||||
/usr/lib/postgresql /usr/include/postgresql /usr/share/postgresql \
|
||||
/etc/postgresql
|
||||
sudo rm -f /usr/bin/pg_config
|
||||
sudo /usr/bin/perl -MCPAN -e 'install IPC::Run'
|
||||
sudo /usr/bin/perl -MCPAN -e 'install Text::Trim'
|
||||
|
||||
- name: Install PG Distribution Postgresql 17
|
||||
run: |
|
||||
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt \
|
||||
$(lsb_release -cs)-pgdg main 17" > /etc/apt/sources.list.d/pgdg.list'
|
||||
sudo wget --quiet -O - \
|
||||
https://www.postgresql.org/media/keys/ACCC4CF8.asc |
|
||||
sudo apt-key add -
|
||||
sudo apt update
|
||||
sudo apt -y install postgresql-17 postgresql-server-dev-17
|
||||
|
||||
- name: Change src owner to postgres
|
||||
run: |
|
||||
sudo chmod o+rx ~
|
||||
sudo chown -R postgres:postgres src
|
||||
|
||||
- name: Build pg_stat_monitor
|
||||
run: |
|
||||
sudo -u postgres bash -c 'make USE_PGXS=1'
|
||||
sudo make USE_PGXS=1 install
|
||||
working-directory: src/pg_stat_monitor
|
||||
|
||||
- name: Start pg_stat_monitor_tests
|
||||
run: |
|
||||
sudo service postgresql stop
|
||||
echo "shared_preload_libraries = 'pg_stat_monitor'" |
|
||||
sudo tee -a /etc/postgresql/17/main/postgresql.conf
|
||||
sudo service postgresql start
|
||||
sudo psql -V
|
||||
export PG_TEST_PORT_DIR=${GITHUB_WORKSPACE}/src/pg_stat_monitor
|
||||
echo $PG_TEST_PORT_DIR
|
||||
sudo -E -u postgres bash -c 'make installcheck USE_PGXS=1'
|
||||
working-directory: src/pg_stat_monitor
|
||||
|
||||
- name: Change dir permissions on fail
|
||||
if: ${{ failure() }}
|
||||
run: |
|
||||
sudo chmod -R ugo+rwx t
|
||||
sudo chmod -R ugo+rwx tmp_check
|
||||
exit 2 # regenerate error so that we can upload files in next step
|
||||
working-directory: src/pg_stat_monitor
|
||||
|
||||
- name: Upload logs on fail
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Regressions diff and postgresql log
|
||||
path: |
|
||||
src/pg_stat_monitor/regression.diffs
|
||||
src/pg_stat_monitor/regression.out
|
||||
src/pg_stat_monitor/logfile
|
||||
src/pg_stat_monitor/t/results/
|
||||
src/pg_stat_monitor/tmp_check/log/
|
||||
!src/pg_stat_monitor/tmp_check/**/archives/*
|
||||
!src/pg_stat_monitor/tmp_check/**/backup/*
|
||||
!src/pg_stat_monitor/tmp_check/**/pgdata/*
|
||||
!src/pg_stat_monitor/tmp_check/**/archives/
|
||||
!src/pg_stat_monitor/tmp_check/**/backup/
|
||||
!src/pg_stat_monitor/tmp_check/**/pgdata/
|
||||
if-no-files-found: warn
|
||||
retention-days: 3
|
4
Makefile
4
Makefile
|
@ -4,7 +4,7 @@ MODULE_big = pg_stat_monitor
|
|||
OBJS = hash_query.o guc.o pg_stat_monitor.o $(WIN32RES)
|
||||
|
||||
EXTENSION = pg_stat_monitor
|
||||
DATA = pg_stat_monitor--2.0.sql pg_stat_monitor--1.0--2.0.sql
|
||||
DATA = pg_stat_monitor--2.0.sql pg_stat_monitor--1.0--2.0.sql pg_stat_monitor--2.0--2.1.sql
|
||||
|
||||
PGFILEDESC = "pg_stat_monitor - execution statistics of SQL statements"
|
||||
|
||||
|
@ -12,7 +12,7 @@ LDFLAGS_SL += $(filter -lm, $(LIBS))
|
|||
|
||||
TAP_TESTS = 1
|
||||
REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/pg_stat_monitor/pg_stat_monitor.conf --inputdir=regression
|
||||
REGRESS = basic version guc pgsm_query_id functions counters relations database error_insert application_name application_name_unique top_query cmd_type error rows tags user
|
||||
REGRESS = basic version guc pgsm_query_id functions counters relations database error_insert application_name application_name_unique top_query cmd_type error rows tags user level_tracking
|
||||
|
||||
# Disabled because these tests require "shared_preload_libraries=pg_stat_statements",
|
||||
# which typical installcheck users do not have (e.g. buildfarm clients).
|
||||
|
|
21
README.md
21
README.md
|
@ -3,6 +3,7 @@
|
|||
[](https://github.com/percona/pg_stat_monitor/actions/workflows/postgresql-14-pgdg-package.yml)
|
||||
[](https://github.com/percona/pg_stat_monitor/actions/workflows/postgresql-15-pgdg-package.yml)
|
||||
[](https://github.com/percona/pg_stat_monitor/actions/workflows/postgresql-16-pgdg-package.yml)
|
||||
[](https://github.com/percona/pg_stat_monitor/actions/workflows/postgresql-17-pgdg-package.yml)
|
||||
|
||||
[](https://badge.fury.io/pg/pg_stat_monitor)
|
||||
[](https://codecov.io/gh/percona/pg_stat_monitor)
|
||||
|
@ -51,7 +52,7 @@ To learn about other features, available in `pg_stat_monitor`, see the [Features
|
|||
|
||||
`pg_stat_monitor` supports PostgreSQL versions 11 and above. It is compatible with both PostgreSQL provided by PostgreSQL Global Development Group (PGDG) and [Percona Distribution for PostgreSQL](https://www.percona.com/software/postgresql-distribution).
|
||||
|
||||
The `RPM` (for RHEL and CentOS) and the `DEB` (for Debian and Ubuntu) packages are available from Percona repositories for PostgreSQL versions [12](https://www.percona.com/downloads/postgresql-distribution-12/LATEST/), [13](https://www.percona.com/downloads/postgresql-distribution-13/LATEST/), [14](https://www.percona.com/downloads/postgresql-distribution-14/LATEST/), [15](https://www.percona.com/downloads/postgresql-distribution-15/LATEST/) and [16](https://www.percona.com/downloads/postgresql-distribution-16/LATEST/).
|
||||
The `RPM` (for RHEL and CentOS) and the `DEB` (for Debian and Ubuntu) packages are available from Percona repositories for PostgreSQL versions [12](https://www.percona.com/downloads/postgresql-distribution-12/LATEST/), [13](https://www.percona.com/downloads/postgresql-distribution-13/LATEST/), [14](https://www.percona.com/downloads/postgresql-distribution-14/LATEST/), [15](https://www.percona.com/downloads/postgresql-distribution-15/LATEST/), [16](https://www.percona.com/downloads/postgresql-distribution-16/LATEST/) and [17](https://www.percona.com/downloads/postgresql-distribution-17/LATEST/).
|
||||
|
||||
The RPM packages are also available in the official PostgreSQL (PGDG) yum repositories.
|
||||
|
||||
|
@ -61,8 +62,8 @@ The `pg_stat_monitor` should work on the latest version of both [Percona Distrib
|
|||
|
||||
| **Distribution** | **Version** | **Provider** |
|
||||
| ---------------- | --------------- | ------------ |
|
||||
|[Percona Distribution for PostgreSQL](https://www.percona.com/software/postgresql-distribution)| [12](https://www.percona.com/downloads/postgresql-distribution-12/LATEST/), [13](https://www.percona.com/downloads/postgresql-distribution-13/LATEST/), [14](https://www.percona.com/downloads/postgresql-distribution-14/LATEST/), [15](https://www.percona.com/downloads/postgresql-distribution-15/LATEST/) and [16](https://www.percona.com/downloads/postgresql-distribution-16/LATEST/)| Percona|
|
||||
| PostgreSQL | 12, 13, 14, 15 and 16 | PostgreSQL Global Development Group (PGDG) |
|
||||
|[Percona Distribution for PostgreSQL](https://www.percona.com/software/postgresql-distribution)| [12](https://www.percona.com/downloads/postgresql-distribution-12/LATEST/), [13](https://www.percona.com/downloads/postgresql-distribution-13/LATEST/), [14](https://www.percona.com/downloads/postgresql-distribution-14/LATEST/), [15](https://www.percona.com/downloads/postgresql-distribution-15/LATEST/), [16](https://www.percona.com/downloads/postgresql-distribution-16/LATEST/) and [17](https://www.percona.com/downloads/postgresql-distribution-17/LATEST/)| Percona|
|
||||
| PostgreSQL | 12, 13, 14, 15, 16 and 17 | PostgreSQL Global Development Group (PGDG) |
|
||||
|
||||
|
||||
### Features
|
||||
|
@ -121,16 +122,16 @@ To install `pg_stat_monitor` from Percona repositories, you need to use the `per
|
|||
percona-release setup ppg-XX
|
||||
```
|
||||
|
||||
Replace XX with the desired PostgreSQL version. For example, to install `pg_stat_monitor ` for PostgreSQL 16, specify `ppg-16`.
|
||||
Replace XX with the desired PostgreSQL version. For example, to install `pg_stat_monitor ` for PostgreSQL 17, specify `ppg-17`.
|
||||
|
||||
3. Install `pg_stat_monitor` package
|
||||
* For Debian and Ubuntu:
|
||||
``` sh
|
||||
apt-get install percona-pg-stat-monitor16
|
||||
apt-get install percona-pg-stat-monitor17
|
||||
```
|
||||
* For RHEL and CentOS:
|
||||
``` sh
|
||||
yum install percona-pg-stat-monitor16
|
||||
yum install percona-pg-stat-monitor17
|
||||
```
|
||||
|
||||
#### Installing from PostgreSQL `yum` repositories
|
||||
|
@ -143,7 +144,7 @@ Install `pg_stat_monitor`:
|
|||
dnf install -y pg_stat_monitor_<VERSION>
|
||||
```
|
||||
|
||||
Replace the `VERSION` variable with the PostgreSQL version you are using (e.g. specify `pg_stat_monitor_16` for PostgreSQL 16)
|
||||
Replace the `VERSION` variable with the PostgreSQL version you are using (e.g. specify `pg_stat_monitor_17` for PostgreSQL 17)
|
||||
|
||||
|
||||
#### Installing from PGXN
|
||||
|
@ -204,7 +205,7 @@ sudo systemctl restart postgresql.service
|
|||
|
||||
|
||||
```sh
|
||||
sudo systemctl restart postgresql-16
|
||||
sudo systemctl restart postgresql-17
|
||||
```
|
||||
|
||||
Create the extension using the [CREATE EXTENSION](https://www.postgresql.org/docs/current/sql-createextension.html) command. Using this command requires the privileges of a superuser or a database owner. Connect to `psql` as a superuser for a database and run the following command:
|
||||
|
@ -280,7 +281,7 @@ To uninstall `pg_stat_monitor`, do the following:
|
|||
|
||||
**Important**: If the `shared_preload_libraries` parameter includes other modules, specify them all for the `ALTER SYSTEM SET` command to keep using them.
|
||||
|
||||
3. Restart the `postgresql` instance to apply the changes. The following command restarts PostgreSQL 16. Replace the version value with the one you are using.
|
||||
3. Restart the `postgresql` instance to apply the changes. The following command restarts PostgreSQL 17. Replace the version value with the one you are using.
|
||||
|
||||
* On Debian and Ubuntu:
|
||||
|
||||
|
@ -292,7 +293,7 @@ To uninstall `pg_stat_monitor`, do the following:
|
|||
|
||||
|
||||
```sh
|
||||
sudo systemctl restart postgresql-16
|
||||
sudo systemctl restart postgresql-17
|
||||
```
|
||||
|
||||
### How we work
|
||||
|
|
|
@ -303,6 +303,8 @@ hash_entry_alloc(pgsmSharedState * pgsm, pgsmHashKey * key, int encoding)
|
|||
memset(&entry->counters, 0, sizeof(Counters));
|
||||
entry->query_text.query_pos = InvalidDsaPointer;
|
||||
entry->counters.info.parent_query = InvalidDsaPointer;
|
||||
entry->stats_since = GetCurrentTimestamp();
|
||||
entry->minmax_stats_since = entry->stats_since;
|
||||
|
||||
/* set the appropriate initial usage count */
|
||||
/* re-initialize the mutex each time ... we assume no one using it */
|
||||
|
|
|
@ -0,0 +1,497 @@
|
|||
/* contrib/pg_stat_monitor/pg_stat_monitor--2.0--2.1.sql */
|
||||
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION pg_stat_monitor" to load this file. \quit
|
||||
|
||||
DROP FUNCTION pg_stat_monitor_internal CASCADE;
|
||||
DROP FUNCTION pgsm_create_view CASCADE;
|
||||
DROP FUNCTION pgsm_create_11_view();
|
||||
DROP FUNCTION pgsm_create_13_view();
|
||||
DROP FUNCTION pgsm_create_14_view();
|
||||
DROP FUNCTION pgsm_create_15_view();
|
||||
|
||||
CREATE FUNCTION pg_stat_monitor_internal(
|
||||
IN showtext boolean,
|
||||
OUT bucket int8, -- 0
|
||||
OUT userid oid,
|
||||
OUT username text,
|
||||
OUT dbid oid,
|
||||
OUT datname text,
|
||||
OUT client_ip int8,
|
||||
|
||||
OUT queryid int8, -- 6
|
||||
OUT planid int8,
|
||||
OUT query text,
|
||||
OUT query_plan text,
|
||||
OUT pgsm_query_id int8,
|
||||
OUT top_queryid int8,
|
||||
OUT top_query text,
|
||||
OUT application_name text,
|
||||
|
||||
OUT relations text, -- 14
|
||||
OUT cmd_type int,
|
||||
OUT elevel int,
|
||||
OUT sqlcode TEXT,
|
||||
OUT message text,
|
||||
OUT bucket_start_time timestamptz,
|
||||
|
||||
OUT calls int8, -- 20
|
||||
|
||||
OUT total_exec_time float8, -- 21
|
||||
OUT min_exec_time float8,
|
||||
OUT max_exec_time float8,
|
||||
OUT mean_exec_time float8,
|
||||
OUT stddev_exec_time float8,
|
||||
|
||||
OUT rows int8, -- 26
|
||||
|
||||
OUT plans int8, -- 27
|
||||
|
||||
OUT total_plan_time float8, -- 28
|
||||
OUT min_plan_time float8,
|
||||
OUT max_plan_time float8,
|
||||
OUT mean_plan_time float8,
|
||||
OUT stddev_plan_time float8,
|
||||
|
||||
OUT shared_blks_hit int8, -- 33
|
||||
OUT shared_blks_read int8,
|
||||
OUT shared_blks_dirtied int8,
|
||||
OUT shared_blks_written int8,
|
||||
OUT local_blks_hit int8,
|
||||
OUT local_blks_read int8,
|
||||
OUT local_blks_dirtied int8,
|
||||
OUT local_blks_written int8,
|
||||
OUT temp_blks_read int8,
|
||||
OUT temp_blks_written int8,
|
||||
OUT shared_blk_read_time float8,
|
||||
OUT shared_blk_write_time float8,
|
||||
OUT local_blk_read_time float8,
|
||||
OUT local_blk_write_time float8,
|
||||
OUT temp_blk_read_time float8,
|
||||
OUT temp_blk_write_time float8,
|
||||
|
||||
OUT resp_calls text, -- 49
|
||||
OUT cpu_user_time float8,
|
||||
OUT cpu_sys_time float8,
|
||||
OUT wal_records int8,
|
||||
OUT wal_fpi int8,
|
||||
OUT wal_bytes numeric,
|
||||
OUT comments TEXT,
|
||||
|
||||
OUT jit_functions int8, -- 56
|
||||
OUT jit_generation_time float8,
|
||||
OUT jit_inlining_count int8,
|
||||
OUT jit_inlining_time float8,
|
||||
OUT jit_optimization_count int8,
|
||||
OUT jit_optimization_time float8,
|
||||
OUT jit_emission_count int8,
|
||||
OUT jit_emission_time float8,
|
||||
OUT jit_deform_count int8,
|
||||
OUT jit_deform_time float8,
|
||||
|
||||
OUT stats_since timestamp with time zone, -- 66
|
||||
OUT minmax_stats_since timestamp with time zone,
|
||||
|
||||
OUT toplevel BOOLEAN, -- 68
|
||||
OUT bucket_done BOOLEAN
|
||||
)
|
||||
RETURNS SETOF record
|
||||
AS 'MODULE_PATHNAME', 'pg_stat_monitor_2_1'
|
||||
LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
|
||||
|
||||
-- Register a view on the function for ease of use.
|
||||
CREATE FUNCTION pgsm_create_11_view() RETURNS INT AS
|
||||
$$
|
||||
BEGIN
|
||||
CREATE VIEW pg_stat_monitor AS SELECT
|
||||
bucket,
|
||||
bucket_start_time AS bucket_start_time,
|
||||
userid,
|
||||
username,
|
||||
dbid,
|
||||
datname,
|
||||
'0.0.0.0'::inet + client_ip AS client_ip,
|
||||
pgsm_query_id,
|
||||
queryid,
|
||||
top_queryid,
|
||||
query,
|
||||
comments,
|
||||
planid,
|
||||
query_plan,
|
||||
top_query,
|
||||
application_name,
|
||||
string_to_array(relations, ',') AS relations,
|
||||
cmd_type,
|
||||
get_cmd_type(cmd_type) AS cmd_type_text,
|
||||
elevel,
|
||||
sqlcode,
|
||||
message,
|
||||
calls,
|
||||
total_exec_time AS total_time,
|
||||
min_exec_time AS min_time,
|
||||
max_exec_time AS max_time,
|
||||
mean_exec_time AS mean_time,
|
||||
stddev_exec_time AS stddev_time,
|
||||
rows,
|
||||
shared_blks_hit,
|
||||
shared_blks_read,
|
||||
shared_blks_dirtied,
|
||||
shared_blks_written,
|
||||
local_blks_hit,
|
||||
local_blks_read,
|
||||
local_blks_dirtied,
|
||||
local_blks_written,
|
||||
temp_blks_read,
|
||||
temp_blks_written,
|
||||
shared_blk_read_time AS blk_read_time,
|
||||
shared_blk_write_time AS blk_write_time,
|
||||
(string_to_array(resp_calls, ',')) resp_calls,
|
||||
cpu_user_time,
|
||||
cpu_sys_time,
|
||||
bucket_done
|
||||
FROM pg_stat_monitor_internal(TRUE)
|
||||
ORDER BY bucket_start_time;
|
||||
RETURN 0;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
CREATE FUNCTION pgsm_create_13_view() RETURNS INT AS
|
||||
$$
|
||||
BEGIN
|
||||
CREATE VIEW pg_stat_monitor AS SELECT
|
||||
bucket,
|
||||
bucket_start_time AS bucket_start_time,
|
||||
userid,
|
||||
username,
|
||||
dbid,
|
||||
datname,
|
||||
'0.0.0.0'::inet + client_ip AS client_ip,
|
||||
pgsm_query_id,
|
||||
queryid,
|
||||
toplevel,
|
||||
top_queryid,
|
||||
query,
|
||||
comments,
|
||||
planid,
|
||||
query_plan,
|
||||
top_query,
|
||||
application_name,
|
||||
string_to_array(relations, ',') AS relations,
|
||||
cmd_type,
|
||||
get_cmd_type(cmd_type) AS cmd_type_text,
|
||||
elevel,
|
||||
sqlcode,
|
||||
message,
|
||||
calls,
|
||||
total_exec_time,
|
||||
min_exec_time,
|
||||
max_exec_time,
|
||||
mean_exec_time,
|
||||
stddev_exec_time,
|
||||
rows,
|
||||
shared_blks_hit,
|
||||
shared_blks_read,
|
||||
shared_blks_dirtied,
|
||||
shared_blks_written,
|
||||
local_blks_hit,
|
||||
local_blks_read,
|
||||
local_blks_dirtied,
|
||||
local_blks_written,
|
||||
temp_blks_read,
|
||||
temp_blks_written,
|
||||
shared_blk_read_time AS blk_read_time,
|
||||
shared_blk_write_time AS blk_write_time,
|
||||
(string_to_array(resp_calls, ',')) resp_calls,
|
||||
cpu_user_time,
|
||||
cpu_sys_time,
|
||||
wal_records,
|
||||
wal_fpi,
|
||||
wal_bytes,
|
||||
bucket_done,
|
||||
-- PostgreSQL-13 Specific Coulumns
|
||||
plans,
|
||||
total_plan_time,
|
||||
min_plan_time,
|
||||
max_plan_time,
|
||||
mean_plan_time,
|
||||
stddev_plan_time
|
||||
FROM pg_stat_monitor_internal(TRUE)
|
||||
ORDER BY bucket_start_time;
|
||||
RETURN 0;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE FUNCTION pgsm_create_14_view() RETURNS INT AS
|
||||
$$
|
||||
BEGIN
|
||||
CREATE VIEW pg_stat_monitor AS SELECT
|
||||
bucket,
|
||||
bucket_start_time AS bucket_start_time,
|
||||
userid,
|
||||
username,
|
||||
dbid,
|
||||
datname,
|
||||
'0.0.0.0'::inet + client_ip AS client_ip,
|
||||
pgsm_query_id,
|
||||
queryid,
|
||||
toplevel,
|
||||
top_queryid,
|
||||
query,
|
||||
comments,
|
||||
planid,
|
||||
query_plan,
|
||||
top_query,
|
||||
application_name,
|
||||
string_to_array(relations, ',') AS relations,
|
||||
cmd_type,
|
||||
get_cmd_type(cmd_type) AS cmd_type_text,
|
||||
elevel,
|
||||
sqlcode,
|
||||
message,
|
||||
calls,
|
||||
total_exec_time,
|
||||
min_exec_time,
|
||||
max_exec_time,
|
||||
mean_exec_time,
|
||||
stddev_exec_time,
|
||||
rows,
|
||||
shared_blks_hit,
|
||||
shared_blks_read,
|
||||
shared_blks_dirtied,
|
||||
shared_blks_written,
|
||||
local_blks_hit,
|
||||
local_blks_read,
|
||||
local_blks_dirtied,
|
||||
local_blks_written,
|
||||
temp_blks_read,
|
||||
temp_blks_written,
|
||||
shared_blk_read_time AS blk_read_time,
|
||||
shared_blk_write_time AS blk_write_time,
|
||||
(string_to_array(resp_calls, ',')) resp_calls,
|
||||
cpu_user_time,
|
||||
cpu_sys_time,
|
||||
wal_records,
|
||||
wal_fpi,
|
||||
wal_bytes,
|
||||
bucket_done,
|
||||
|
||||
plans,
|
||||
total_plan_time,
|
||||
min_plan_time,
|
||||
max_plan_time,
|
||||
mean_plan_time,
|
||||
stddev_plan_time
|
||||
FROM pg_stat_monitor_internal(TRUE)
|
||||
ORDER BY bucket_start_time;
|
||||
RETURN 0;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE FUNCTION pgsm_create_15_view() RETURNS INT AS
|
||||
$$
|
||||
BEGIN
|
||||
CREATE VIEW pg_stat_monitor AS SELECT
|
||||
bucket,
|
||||
bucket_start_time AS bucket_start_time,
|
||||
userid,
|
||||
username,
|
||||
dbid,
|
||||
datname,
|
||||
'0.0.0.0'::inet + client_ip AS client_ip,
|
||||
pgsm_query_id,
|
||||
queryid,
|
||||
toplevel,
|
||||
top_queryid,
|
||||
query,
|
||||
comments,
|
||||
planid,
|
||||
query_plan,
|
||||
top_query,
|
||||
application_name,
|
||||
string_to_array(relations, ',') AS relations,
|
||||
cmd_type,
|
||||
get_cmd_type(cmd_type) AS cmd_type_text,
|
||||
elevel,
|
||||
sqlcode,
|
||||
message,
|
||||
calls,
|
||||
total_exec_time,
|
||||
min_exec_time,
|
||||
max_exec_time,
|
||||
mean_exec_time,
|
||||
stddev_exec_time,
|
||||
rows,
|
||||
shared_blks_hit,
|
||||
shared_blks_read,
|
||||
shared_blks_dirtied,
|
||||
shared_blks_written,
|
||||
local_blks_hit,
|
||||
local_blks_read,
|
||||
local_blks_dirtied,
|
||||
local_blks_written,
|
||||
temp_blks_read,
|
||||
temp_blks_written,
|
||||
shared_blk_read_time AS blk_read_time,
|
||||
shared_blk_write_time AS blk_write_time,
|
||||
temp_blk_read_time,
|
||||
temp_blk_write_time,
|
||||
|
||||
(string_to_array(resp_calls, ',')) resp_calls,
|
||||
cpu_user_time,
|
||||
cpu_sys_time,
|
||||
wal_records,
|
||||
wal_fpi,
|
||||
wal_bytes,
|
||||
bucket_done,
|
||||
|
||||
plans,
|
||||
total_plan_time,
|
||||
min_plan_time,
|
||||
max_plan_time,
|
||||
mean_plan_time,
|
||||
stddev_plan_time,
|
||||
|
||||
jit_functions,
|
||||
jit_generation_time,
|
||||
jit_inlining_count,
|
||||
jit_inlining_time,
|
||||
jit_optimization_count,
|
||||
jit_optimization_time,
|
||||
jit_emission_count,
|
||||
jit_emission_time
|
||||
|
||||
FROM pg_stat_monitor_internal(TRUE)
|
||||
ORDER BY bucket_start_time;
|
||||
RETURN 0;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE FUNCTION pgsm_create_17_view() RETURNS INT AS
|
||||
$$
|
||||
BEGIN
|
||||
CREATE VIEW pg_stat_monitor AS SELECT
|
||||
bucket,
|
||||
bucket_start_time,
|
||||
userid,
|
||||
username,
|
||||
dbid,
|
||||
datname,
|
||||
'0.0.0.0'::inet + client_ip AS client_ip,
|
||||
pgsm_query_id,
|
||||
queryid,
|
||||
toplevel,
|
||||
top_queryid,
|
||||
query,
|
||||
comments,
|
||||
planid,
|
||||
query_plan,
|
||||
top_query,
|
||||
application_name,
|
||||
string_to_array(relations, ',') AS relations,
|
||||
cmd_type,
|
||||
get_cmd_type(cmd_type) AS cmd_type_text,
|
||||
elevel,
|
||||
sqlcode,
|
||||
message,
|
||||
calls,
|
||||
total_exec_time,
|
||||
min_exec_time,
|
||||
max_exec_time,
|
||||
mean_exec_time,
|
||||
stddev_exec_time,
|
||||
rows,
|
||||
shared_blks_hit,
|
||||
shared_blks_read,
|
||||
shared_blks_dirtied,
|
||||
shared_blks_written,
|
||||
local_blks_hit,
|
||||
local_blks_read,
|
||||
local_blks_dirtied,
|
||||
local_blks_written,
|
||||
temp_blks_read,
|
||||
temp_blks_written,
|
||||
shared_blk_read_time,
|
||||
shared_blk_write_time,
|
||||
local_blk_read_time,
|
||||
local_blk_write_time,
|
||||
temp_blk_read_time,
|
||||
temp_blk_write_time,
|
||||
|
||||
(string_to_array(resp_calls, ',')) resp_calls,
|
||||
cpu_user_time,
|
||||
cpu_sys_time,
|
||||
wal_records,
|
||||
wal_fpi,
|
||||
wal_bytes,
|
||||
bucket_done,
|
||||
|
||||
plans,
|
||||
total_plan_time,
|
||||
min_plan_time,
|
||||
max_plan_time,
|
||||
mean_plan_time,
|
||||
stddev_plan_time,
|
||||
|
||||
jit_functions,
|
||||
jit_generation_time,
|
||||
jit_inlining_count,
|
||||
jit_inlining_time,
|
||||
jit_optimization_count,
|
||||
jit_optimization_time,
|
||||
jit_emission_count,
|
||||
jit_emission_time,
|
||||
jit_deform_count,
|
||||
jit_deform_time,
|
||||
|
||||
stats_since,
|
||||
minmax_stats_since
|
||||
|
||||
FROM pg_stat_monitor_internal(TRUE)
|
||||
ORDER BY bucket_start_time;
|
||||
RETURN 0;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE FUNCTION pgsm_create_view() RETURNS INT AS
|
||||
$$
|
||||
DECLARE ver integer;
|
||||
BEGIN
|
||||
SELECT current_setting('server_version_num') INTO ver;
|
||||
IF (ver >= 170000) THEN
|
||||
return pgsm_create_17_view();
|
||||
END IF;
|
||||
IF (ver >= 150000) THEN
|
||||
return pgsm_create_15_view();
|
||||
END IF;
|
||||
IF (ver >= 140000) THEN
|
||||
return pgsm_create_14_view();
|
||||
END IF;
|
||||
IF (ver >= 130000) THEN
|
||||
return pgsm_create_13_view();
|
||||
END IF;
|
||||
IF (ver >= 110000) THEN
|
||||
return pgsm_create_11_view();
|
||||
END IF;
|
||||
RETURN 0;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
SELECT pgsm_create_view();
|
||||
REVOKE ALL ON FUNCTION pgsm_create_view FROM PUBLIC;
|
||||
REVOKE ALL ON FUNCTION pgsm_create_11_view FROM PUBLIC;
|
||||
REVOKE ALL ON FUNCTION pgsm_create_13_view FROM PUBLIC;
|
||||
REVOKE ALL ON FUNCTION pgsm_create_14_view FROM PUBLIC;
|
||||
REVOKE ALL ON FUNCTION pgsm_create_15_view FROM PUBLIC;
|
||||
REVOKE ALL ON FUNCTION pgsm_create_17_view FROM PUBLIC;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION range TO PUBLIC;
|
||||
GRANT EXECUTE ON FUNCTION decode_error_level TO PUBLIC;
|
||||
GRANT EXECUTE ON FUNCTION get_histogram_timings TO PUBLIC;
|
||||
GRANT EXECUTE ON FUNCTION get_cmd_type TO PUBLIC;
|
||||
GRANT EXECUTE ON FUNCTION pg_stat_monitor_internal TO PUBLIC;
|
||||
|
||||
GRANT SELECT ON pg_stat_monitor TO PUBLIC;
|
||||
|
||||
-- Reset is only available to super user
|
||||
REVOKE ALL ON FUNCTION pg_stat_monitor_reset FROM PUBLIC;
|
|
@ -31,16 +31,18 @@
|
|||
typedef enum pgsmVersion
|
||||
{
|
||||
PGSM_V1_0 = 0,
|
||||
PGSM_V2_0
|
||||
PGSM_V2_0,
|
||||
PGSM_V2_1
|
||||
} pgsmVersion;
|
||||
|
||||
PG_MODULE_MAGIC;
|
||||
|
||||
#define BUILD_VERSION "2.0.4"
|
||||
#define BUILD_VERSION "2.1.0"
|
||||
|
||||
/* Number of output arguments (columns) for various API versions */
|
||||
#define PG_STAT_MONITOR_COLS_V1_0 52
|
||||
#define PG_STAT_MONITOR_COLS_V2_0 64
|
||||
#define PG_STAT_MONITOR_COLS_V2_1 70
|
||||
#define PG_STAT_MONITOR_COLS PG_STAT_MONITOR_COLS_V2_0 /* maximum of above */
|
||||
|
||||
#define PGSM_TEXT_FILE PGSTAT_STAT_PERMANENT_DIRECTORY "pg_stat_monitor_query"
|
||||
|
@ -71,11 +73,12 @@ do \
|
|||
/*---- Initicalization Function Declarations ----*/
|
||||
void _PG_init(void);
|
||||
|
||||
/* Current nesting depth of ExecutorRun+ProcessUtility calls */
|
||||
static int exec_nested_level = 0;
|
||||
/* Current nesting depth of planner/ExecutorRun/ProcessUtility calls */
|
||||
static int nesting_level = 0;
|
||||
volatile bool __pgsm_do_not_capture_error = false;
|
||||
|
||||
#if PG_VERSION_NUM >= 130000
|
||||
#if PG_VERSION_NUM >= 130000 && PG_VERSION_NUM < 170000
|
||||
/* Before planner nesting level was conunted separately */
|
||||
static int plan_nested_level = 0;
|
||||
#endif
|
||||
|
||||
|
@ -145,6 +148,7 @@ PG_FUNCTION_INFO_V1(pg_stat_monitor_version);
|
|||
PG_FUNCTION_INFO_V1(pg_stat_monitor_reset);
|
||||
PG_FUNCTION_INFO_V1(pg_stat_monitor_1_0);
|
||||
PG_FUNCTION_INFO_V1(pg_stat_monitor_2_0);
|
||||
PG_FUNCTION_INFO_V1(pg_stat_monitor_2_1);
|
||||
PG_FUNCTION_INFO_V1(pg_stat_monitor);
|
||||
PG_FUNCTION_INFO_V1(get_histogram_timings);
|
||||
PG_FUNCTION_INFO_V1(pg_stat_monitor_hook_stats);
|
||||
|
@ -197,11 +201,6 @@ DECLARE_HOOK(void pgsm_ProcessUtility, PlannedStmt *pstmt, const char *queryStri
|
|||
static uint64 pgsm_hash_string(const char *str, int len);
|
||||
char *unpack_sql_state(int sql_state);
|
||||
|
||||
#define PGSM_HANDLED_UTILITY(n) (!IsA(n, ExecuteStmt) && \
|
||||
!IsA(n, PrepareStmt) && \
|
||||
!IsA(n, DeallocateStmt))
|
||||
|
||||
|
||||
static pgsmEntry * pgsm_create_hash_entry(uint64 bucket_id, uint64 queryid, PlanInfo * plan_info);
|
||||
static void pgsm_add_to_list(pgsmEntry * entry, char *query_text, int query_len);
|
||||
static pgsmEntry * pgsm_get_entry_for_query(uint64 queryid, PlanInfo * plan_info, const char *query_text, int query_len, bool create);
|
||||
|
@ -425,17 +424,18 @@ pgsm_post_parse_analyze_internal(ParseState *pstate, Query *query, JumbleState *
|
|||
}
|
||||
}
|
||||
|
||||
if (!pgsm_enabled(exec_nested_level))
|
||||
if (!pgsm_enabled(nesting_level))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Clear queryId for prepared statements related utility, as those will
|
||||
* inherit from the underlying statement's one (except DEALLOCATE which is
|
||||
* entirely untracked).
|
||||
* If it's EXECUTE, clear the queryId so that stats will accumulate for
|
||||
* the underlying PREPARE. But don't do this if we're not tracking
|
||||
* utility statements, to avoid messing up another extension that might be
|
||||
* tracking them.
|
||||
*/
|
||||
if (query->utilityStmt)
|
||||
{
|
||||
if (pgsm_track_utility && !PGSM_HANDLED_UTILITY(query->utilityStmt))
|
||||
if (pgsm_track_utility && IsA(query->utilityStmt, ExecuteStmt))
|
||||
query->queryId = UINT64CONST(0);
|
||||
|
||||
return;
|
||||
|
@ -568,7 +568,7 @@ pgsm_ExecutorStart(QueryDesc *queryDesc, int eflags)
|
|||
* counting of optimizable statements that are directly contained in
|
||||
* utility statements.
|
||||
*/
|
||||
if (pgsm_enabled(exec_nested_level) &&
|
||||
if (pgsm_enabled(nesting_level) &&
|
||||
queryDesc->plannedstmt->queryId != UINT64CONST(0))
|
||||
{
|
||||
/*
|
||||
|
@ -599,37 +599,37 @@ static void
|
|||
pgsm_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count,
|
||||
bool execute_once)
|
||||
{
|
||||
if (exec_nested_level >= 0 && exec_nested_level < max_stack_depth)
|
||||
if (nesting_level >= 0 && nesting_level < max_stack_depth)
|
||||
{
|
||||
nested_queryids[exec_nested_level] = queryDesc->plannedstmt->queryId;
|
||||
nested_query_txts[exec_nested_level] = strdup(queryDesc->sourceText);
|
||||
nested_queryids[nesting_level] = queryDesc->plannedstmt->queryId;
|
||||
nested_query_txts[nesting_level] = strdup(queryDesc->sourceText);
|
||||
}
|
||||
|
||||
exec_nested_level++;
|
||||
nesting_level++;
|
||||
PG_TRY();
|
||||
{
|
||||
if (prev_ExecutorRun)
|
||||
prev_ExecutorRun(queryDesc, direction, count, execute_once);
|
||||
else
|
||||
standard_ExecutorRun(queryDesc, direction, count, execute_once);
|
||||
exec_nested_level--;
|
||||
if (exec_nested_level >= 0 && exec_nested_level < max_stack_depth)
|
||||
nesting_level--;
|
||||
if (nesting_level >= 0 && nesting_level < max_stack_depth)
|
||||
{
|
||||
nested_queryids[exec_nested_level] = UINT64CONST(0);
|
||||
if (nested_query_txts[exec_nested_level])
|
||||
free(nested_query_txts[exec_nested_level]);
|
||||
nested_query_txts[exec_nested_level] = NULL;
|
||||
nested_queryids[nesting_level] = UINT64CONST(0);
|
||||
if (nested_query_txts[nesting_level])
|
||||
free(nested_query_txts[nesting_level]);
|
||||
nested_query_txts[nesting_level] = NULL;
|
||||
}
|
||||
}
|
||||
PG_CATCH();
|
||||
{
|
||||
exec_nested_level--;
|
||||
if (exec_nested_level >= 0 && exec_nested_level < max_stack_depth)
|
||||
nesting_level--;
|
||||
if (nesting_level >= 0 && nesting_level < max_stack_depth)
|
||||
{
|
||||
nested_queryids[exec_nested_level] = UINT64CONST(0);
|
||||
if (nested_query_txts[exec_nested_level])
|
||||
free(nested_query_txts[exec_nested_level]);
|
||||
nested_query_txts[exec_nested_level] = NULL;
|
||||
nested_queryids[nesting_level] = UINT64CONST(0);
|
||||
if (nested_query_txts[nesting_level])
|
||||
free(nested_query_txts[nesting_level]);
|
||||
nested_query_txts[nesting_level] = NULL;
|
||||
}
|
||||
PG_RE_THROW();
|
||||
}
|
||||
|
@ -642,7 +642,7 @@ pgsm_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count,
|
|||
static void
|
||||
pgsm_ExecutorFinish(QueryDesc *queryDesc)
|
||||
{
|
||||
exec_nested_level++;
|
||||
nesting_level++;
|
||||
|
||||
PG_TRY();
|
||||
{
|
||||
|
@ -650,11 +650,11 @@ pgsm_ExecutorFinish(QueryDesc *queryDesc)
|
|||
prev_ExecutorFinish(queryDesc);
|
||||
else
|
||||
standard_ExecutorFinish(queryDesc);
|
||||
exec_nested_level--;
|
||||
nesting_level--;
|
||||
}
|
||||
PG_CATCH();
|
||||
{
|
||||
exec_nested_level--;
|
||||
nesting_level--;
|
||||
PG_RE_THROW();
|
||||
}
|
||||
PG_END_TRY();
|
||||
|
@ -722,7 +722,7 @@ pgsm_ExecutorEnd(QueryDesc *queryDesc)
|
|||
MemoryContextSwitchTo(oldctx);
|
||||
}
|
||||
|
||||
if (queryId != UINT64CONST(0) && queryDesc->totaltime && pgsm_enabled(exec_nested_level))
|
||||
if (queryId != UINT64CONST(0) && queryDesc->totaltime && pgsm_enabled(nesting_level))
|
||||
{
|
||||
entry = pgsm_get_entry_for_query(queryId, plan_ptr, (char *) queryDesc->sourceText, strlen(queryDesc->sourceText), true);
|
||||
if (!entry)
|
||||
|
@ -868,8 +868,14 @@ pgsm_planner_hook(Query *parse, const char *query_string, int cursorOptions, Par
|
|||
* top level planner call.
|
||||
*/
|
||||
|
||||
if (pgsm_enabled(plan_nested_level + exec_nested_level) &&
|
||||
pgsm_track_planning && query_string && parse->queryId != UINT64CONST(0))
|
||||
bool enabled;
|
||||
#if PG_VERSION_NUM >= 170000
|
||||
enabled = pgsm_enabled(nesting_level);
|
||||
#else
|
||||
enabled = pgsm_enabled(plan_nested_level + nesting_level);
|
||||
#endif
|
||||
|
||||
if (enabled && pgsm_track_planning && query_string && parse->queryId != UINT64CONST(0))
|
||||
{
|
||||
pgsmEntry *entry = NULL;
|
||||
instr_time start;
|
||||
|
@ -892,7 +898,11 @@ pgsm_planner_hook(Query *parse, const char *query_string, int cursorOptions, Par
|
|||
if (MemoryContextIsValid(MessageContext))
|
||||
entry = pgsm_get_entry_for_query(parse->queryId, NULL, query_string, strlen(query_string), true);
|
||||
|
||||
#if PG_VERSION_NUM >= 170000
|
||||
nesting_level++;
|
||||
#else
|
||||
plan_nested_level++;
|
||||
#endif
|
||||
PG_TRY();
|
||||
{
|
||||
/*
|
||||
|
@ -909,7 +919,11 @@ pgsm_planner_hook(Query *parse, const char *query_string, int cursorOptions, Par
|
|||
}
|
||||
PG_FINALLY();
|
||||
{
|
||||
#if PG_VERSION_NUM >= 170000
|
||||
nesting_level--;
|
||||
#else
|
||||
plan_nested_level--;
|
||||
#endif
|
||||
}
|
||||
PG_END_TRY();
|
||||
|
||||
|
@ -945,19 +959,38 @@ pgsm_planner_hook(Query *parse, const char *query_string, int cursorOptions, Par
|
|||
else
|
||||
{
|
||||
/*
|
||||
* Even though we're not tracking plan time for this statement, we
|
||||
* must still increment the nesting level, to ensure that functions
|
||||
* evaluated during planning are not seen as top-level calls.
|
||||
*
|
||||
* If there is a previous installed hook, then assume it's going to
|
||||
* call standard_planner() function, otherwise we call the function
|
||||
* here. This is to avoid calling standard_planner() function twice,
|
||||
* since it modifies the first argument (Query *), the second call
|
||||
* would trigger an assertion failure.
|
||||
*/
|
||||
plan_nested_level++;
|
||||
|
||||
if (planner_hook_next)
|
||||
result = planner_hook_next(parse, query_string, cursorOptions, boundParams);
|
||||
else
|
||||
result = standard_planner(parse, query_string, cursorOptions, boundParams);
|
||||
plan_nested_level--;
|
||||
#if PG_VERSION_NUM >= 170000
|
||||
nesting_level++;
|
||||
#else
|
||||
plan_nested_level++;
|
||||
#endif
|
||||
PG_TRY();
|
||||
{
|
||||
if (planner_hook_next)
|
||||
result = planner_hook_next(parse, query_string, cursorOptions, boundParams);
|
||||
else
|
||||
result = standard_planner(parse, query_string, cursorOptions, boundParams);
|
||||
}
|
||||
PG_FINALLY();
|
||||
{
|
||||
#if PG_VERSION_NUM >= 170000
|
||||
nesting_level--;
|
||||
#else
|
||||
plan_nested_level--;
|
||||
#endif
|
||||
}
|
||||
PG_END_TRY();
|
||||
|
||||
}
|
||||
return result;
|
||||
|
@ -995,6 +1028,7 @@ pgsm_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||
{
|
||||
Node *parsetree = pstmt->utilityStmt;
|
||||
uint64 queryId = 0;
|
||||
bool enabled = pgsm_track_utility && pgsm_enabled(nesting_level);
|
||||
|
||||
#if PG_VERSION_NUM < 140000
|
||||
int len = strlen(queryString);
|
||||
|
@ -1012,7 +1046,7 @@ pgsm_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||
* since we are already measuring the statement's costs at the utility
|
||||
* level.
|
||||
*/
|
||||
if (pgsm_track_utility && pgsm_enabled(exec_nested_level))
|
||||
if (enabled)
|
||||
pstmt->queryId = UINT64CONST(0);
|
||||
#endif
|
||||
|
||||
|
@ -1025,13 +1059,16 @@ pgsm_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||
* hash table entry for the PREPARE (with hash calculated from the query
|
||||
* string), and then a different one with the same query string (but hash
|
||||
* calculated from the query tree) would be used to accumulate costs of
|
||||
* ensuing EXECUTEs. This would be confusing, and inconsistent with other
|
||||
* cases where planning time is not included at all.
|
||||
* ensuing EXECUTEs. This would be confusing. Since PREPARE doesn't
|
||||
* actually run the planner (only parse+rewrite), its costs are generally
|
||||
* pretty negligible and it seems okay to just ignore it.
|
||||
*
|
||||
* Likewise, we don't track execution of DEALLOCATE.
|
||||
*/
|
||||
if (pgsm_track_utility && pgsm_enabled(exec_nested_level) &&
|
||||
PGSM_HANDLED_UTILITY(parsetree))
|
||||
if (enabled &&
|
||||
!IsA(parsetree, ExecuteStmt) &&
|
||||
!IsA(parsetree, PrepareStmt) &&
|
||||
!IsA(parsetree, DeallocateStmt))
|
||||
{
|
||||
pgsmEntry *entry;
|
||||
char *query_text;
|
||||
|
@ -1052,7 +1089,7 @@ pgsm_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||
elog(DEBUG1, "[pg_stat_monitor] pgsm_ProcessUtility: Failed to execute getrusage.");
|
||||
|
||||
INSTR_TIME_SET_CURRENT(start);
|
||||
exec_nested_level++;
|
||||
nesting_level++;
|
||||
|
||||
PG_TRY();
|
||||
{
|
||||
|
@ -1092,11 +1129,11 @@ pgsm_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||
dest,
|
||||
completionTag);
|
||||
#endif
|
||||
exec_nested_level--;
|
||||
nesting_level--;
|
||||
}
|
||||
PG_CATCH();
|
||||
{
|
||||
exec_nested_level--;
|
||||
nesting_level--;
|
||||
PG_RE_THROW();
|
||||
}
|
||||
|
||||
|
@ -1182,41 +1219,80 @@ pgsm_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Even though we're not tracking execution time for this statement,
|
||||
* we must still increment the nesting level, to ensure that functions
|
||||
* evaluated within it are not seen as top-level calls. But don't do
|
||||
* so for EXECUTE; that way, when control reaches pgss_planner or
|
||||
* pgss_ExecutorStart, we will treat the costs as top-level if
|
||||
* appropriate. Likewise, don't bump for PREPARE, so that parse
|
||||
* analysis will treat the statement as top-level if appropriate.
|
||||
*
|
||||
* Likewise, we don't track execution of DEALLOCATE.
|
||||
*
|
||||
* To be absolutely certain we don't mess up the nesting level,
|
||||
* evaluate the bump_level condition just once.
|
||||
*/
|
||||
|
||||
#if PG_VERSION_NUM >= 170000
|
||||
bool bump_level =
|
||||
!IsA(parsetree, ExecuteStmt) &&
|
||||
!IsA(parsetree, PrepareStmt) &&
|
||||
!IsA(parsetree, DeallocateStmt);
|
||||
|
||||
if (bump_level)
|
||||
nesting_level++;
|
||||
|
||||
PG_TRY();
|
||||
{
|
||||
#endif
|
||||
#if PG_VERSION_NUM >= 140000
|
||||
if (prev_ProcessUtility)
|
||||
prev_ProcessUtility(pstmt, queryString,
|
||||
readOnlyTree,
|
||||
context, params, queryEnv,
|
||||
dest,
|
||||
qc);
|
||||
else
|
||||
standard_ProcessUtility(pstmt, queryString,
|
||||
if (prev_ProcessUtility)
|
||||
prev_ProcessUtility(pstmt, queryString,
|
||||
readOnlyTree,
|
||||
context, params, queryEnv,
|
||||
dest,
|
||||
qc);
|
||||
else
|
||||
standard_ProcessUtility(pstmt, queryString,
|
||||
readOnlyTree,
|
||||
context, params, queryEnv,
|
||||
dest,
|
||||
qc);
|
||||
#elif PG_VERSION_NUM >= 130000
|
||||
if (prev_ProcessUtility)
|
||||
prev_ProcessUtility(pstmt, queryString,
|
||||
context, params, queryEnv,
|
||||
dest,
|
||||
qc);
|
||||
else
|
||||
standard_ProcessUtility(pstmt, queryString,
|
||||
if (prev_ProcessUtility)
|
||||
prev_ProcessUtility(pstmt, queryString,
|
||||
context, params, queryEnv,
|
||||
dest,
|
||||
qc);
|
||||
else
|
||||
standard_ProcessUtility(pstmt, queryString,
|
||||
context, params, queryEnv,
|
||||
dest,
|
||||
qc);
|
||||
#else
|
||||
if (prev_ProcessUtility)
|
||||
prev_ProcessUtility(pstmt, queryString,
|
||||
context, params, queryEnv,
|
||||
dest,
|
||||
completionTag);
|
||||
else
|
||||
standard_ProcessUtility(pstmt, queryString,
|
||||
if (prev_ProcessUtility)
|
||||
prev_ProcessUtility(pstmt, queryString,
|
||||
context, params, queryEnv,
|
||||
dest,
|
||||
completionTag);
|
||||
else
|
||||
standard_ProcessUtility(pstmt, queryString,
|
||||
context, params, queryEnv,
|
||||
dest,
|
||||
completionTag);
|
||||
#endif
|
||||
#if PG_VERSION_NUM >= 170000
|
||||
if (bump_level)
|
||||
nesting_level--;
|
||||
}
|
||||
PG_CATCH();
|
||||
{
|
||||
if (bump_level)
|
||||
nesting_level--;
|
||||
PG_RE_THROW();
|
||||
}
|
||||
PG_END_TRY();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1358,9 +1434,13 @@ pgsm_update_entry(pgsmEntry * entry,
|
|||
int sqlcode_len = error_info ? strlen(error_info->sqlcode) : 0;
|
||||
int plan_text_len = plan_info ? plan_info->plan_len : 0;
|
||||
|
||||
/* Start collecting data for next bucket and reset all counters */
|
||||
/* Start collecting data for next bucket and reset all counters and timestamps */
|
||||
if (reset)
|
||||
{
|
||||
memset(&entry->counters, 0, sizeof(Counters));
|
||||
entry->stats_since = GetCurrentTimestamp();
|
||||
entry->minmax_stats_since = entry->stats_since;
|
||||
}
|
||||
|
||||
/* volatile block */
|
||||
{
|
||||
|
@ -1457,14 +1537,14 @@ pgsm_update_entry(pgsmEntry * entry,
|
|||
e->counters.info.num_relations = num_relations;
|
||||
_snprintf2(e->counters.info.relations, relations, num_relations, REL_LEN);
|
||||
|
||||
if (exec_nested_level > 0 && e->counters.info.parentid == 0 && pgsm_track == PGSM_TRACK_ALL)
|
||||
if (nesting_level > 0 && e->counters.info.parentid == 0 && pgsm_track == PGSM_TRACK_ALL)
|
||||
{
|
||||
if (exec_nested_level >= 0 && exec_nested_level < max_stack_depth)
|
||||
if (nesting_level >= 0 && nesting_level < max_stack_depth)
|
||||
{
|
||||
int parent_query_len = nested_query_txts[exec_nested_level - 1] ?
|
||||
strlen(nested_query_txts[exec_nested_level - 1]) : 0;
|
||||
int parent_query_len = nested_query_txts[nesting_level - 1] ?
|
||||
strlen(nested_query_txts[nesting_level - 1]) : 0;
|
||||
|
||||
e->counters.info.parentid = nested_queryids[exec_nested_level - 1];
|
||||
e->counters.info.parentid = nested_queryids[nesting_level - 1];
|
||||
e->counters.info.parent_query = InvalidDsaPointer;
|
||||
/* If we have a parent query, store it in the raw dsa area */
|
||||
if (parent_query_len > 0)
|
||||
|
@ -1482,7 +1562,7 @@ pgsm_update_entry(pgsmEntry * entry,
|
|||
if (DsaPointerIsValid(qry))
|
||||
{
|
||||
qry_buff = dsa_get_address(query_dsa_area, qry);
|
||||
memcpy(qry_buff, nested_query_txts[exec_nested_level - 1], parent_query_len);
|
||||
memcpy(qry_buff, nested_query_txts[nesting_level - 1], parent_query_len);
|
||||
qry_buff[parent_query_len] = 0;
|
||||
/* store the dsa pointer for parent query text */
|
||||
e->counters.info.parent_query = qry;
|
||||
|
@ -1518,15 +1598,32 @@ pgsm_update_entry(pgsmEntry * entry,
|
|||
e->counters.blocks.local_blks_written += bufusage->local_blks_written;
|
||||
e->counters.blocks.temp_blks_read += bufusage->temp_blks_read;
|
||||
e->counters.blocks.temp_blks_written += bufusage->temp_blks_written;
|
||||
e->counters.blocks.blk_read_time += INSTR_TIME_GET_MILLISEC(bufusage->blk_read_time);
|
||||
e->counters.blocks.blk_write_time += INSTR_TIME_GET_MILLISEC(bufusage->blk_write_time);
|
||||
|
||||
#if PG_VERSION_NUM < 170000
|
||||
e->counters.blocks.shared_blk_read_time += INSTR_TIME_GET_MILLISEC(bufusage->blk_read_time);
|
||||
e->counters.blocks.shared_blk_write_time += INSTR_TIME_GET_MILLISEC(bufusage->blk_write_time);
|
||||
#else
|
||||
e->counters.blocks.shared_blk_read_time += INSTR_TIME_GET_MILLISEC(bufusage->shared_blk_read_time);
|
||||
e->counters.blocks.shared_blk_write_time += INSTR_TIME_GET_MILLISEC(bufusage->shared_blk_write_time);
|
||||
e->counters.blocks.local_blk_read_time += INSTR_TIME_GET_MILLISEC(bufusage->local_blk_read_time);
|
||||
e->counters.blocks.local_blk_write_time += INSTR_TIME_GET_MILLISEC(bufusage->local_blk_write_time);
|
||||
#endif
|
||||
|
||||
#if PG_VERSION_NUM >= 150000
|
||||
e->counters.blocks.temp_blk_read_time += INSTR_TIME_GET_MILLISEC(bufusage->temp_blk_read_time);
|
||||
e->counters.blocks.temp_blk_write_time += INSTR_TIME_GET_MILLISEC(bufusage->temp_blk_write_time);
|
||||
#endif
|
||||
|
||||
memcpy((void *) &e->counters.blocks.instr_blk_read_time, &bufusage->blk_read_time, sizeof(instr_time));
|
||||
memcpy((void *) &e->counters.blocks.instr_blk_write_time, &bufusage->blk_write_time, sizeof(instr_time));
|
||||
#if PG_VERSION_NUM < 170000
|
||||
memcpy((void *) &e->counters.blocks.instr_shared_blk_read_time, &bufusage->blk_read_time, sizeof(instr_time));
|
||||
memcpy((void *) &e->counters.blocks.instr_shared_blk_write_time, &bufusage->blk_write_time, sizeof(instr_time));
|
||||
#else
|
||||
memcpy((void *) &e->counters.blocks.instr_shared_blk_read_time, &bufusage->shared_blk_read_time, sizeof(instr_time));
|
||||
memcpy((void *) &e->counters.blocks.instr_shared_blk_write_time, &bufusage->shared_blk_write_time, sizeof(instr_time));
|
||||
memcpy((void *) &e->counters.blocks.instr_local_blk_write_time, &bufusage->local_blk_write_time, sizeof(instr_time));
|
||||
memcpy((void *) &e->counters.blocks.instr_local_blk_write_time, &bufusage->local_blk_write_time, sizeof(instr_time));
|
||||
#endif
|
||||
|
||||
|
||||
#if PG_VERSION_NUM >= 150000
|
||||
memcpy((void *) &e->counters.blocks.instr_temp_blk_read_time, &bufusage->temp_blk_read_time, sizeof(bufusage->temp_blk_read_time));
|
||||
|
@ -1564,6 +1661,12 @@ pgsm_update_entry(pgsmEntry * entry,
|
|||
e->counters.jitinfo.jit_emission_count++;
|
||||
e->counters.jitinfo.jit_emission_time += INSTR_TIME_GET_MILLISEC(jitusage->emission_counter);
|
||||
|
||||
#if PG_VERSION_NUM >= 170000
|
||||
if (INSTR_TIME_GET_MILLISEC(jitusage->deform_counter))
|
||||
e->counters.jitinfo.jit_deform_count++;
|
||||
e->counters.jitinfo.jit_deform_time += INSTR_TIME_GET_MILLISEC(jitusage->deform_counter);
|
||||
#endif
|
||||
|
||||
/* Only do this for local storage scenarios */
|
||||
if (kind != PGSM_STORE)
|
||||
{
|
||||
|
@ -1571,6 +1674,10 @@ pgsm_update_entry(pgsmEntry * entry,
|
|||
memcpy((void *) &e->counters.jitinfo.instr_inlining_counter, &jitusage->inlining_counter, sizeof(instr_time));
|
||||
memcpy((void *) &e->counters.jitinfo.instr_optimization_counter, &jitusage->optimization_counter, sizeof(instr_time));
|
||||
memcpy((void *) &e->counters.jitinfo.instr_emission_counter, &jitusage->emission_counter, sizeof(instr_time));
|
||||
|
||||
#if PG_VERSION_NUM >= 170000
|
||||
memcpy((void *) &e->counters.jitinfo.instr_deform_counter, &jitusage->deform_counter, sizeof(instr_time));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1716,7 +1823,11 @@ pgsm_create_hash_entry(uint64 bucket_id, uint64 queryid, PlanInfo * plan_info)
|
|||
#if PG_VERSION_NUM < 140000
|
||||
entry->key.toplevel = 1;
|
||||
#else
|
||||
entry->key.toplevel = ((exec_nested_level + plan_nested_level) == 0);
|
||||
#if PG_VERSION_NUM >= 170000
|
||||
entry->key.toplevel = ((nesting_level) == 0);
|
||||
#else
|
||||
entry->key.toplevel = ((nesting_level + plan_nested_level) == 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (IsTransactionState())
|
||||
|
@ -1802,8 +1913,15 @@ pgsm_store(pgsmEntry * entry)
|
|||
bufusage.temp_blks_read = entry->counters.blocks.temp_blks_read;
|
||||
bufusage.temp_blks_written = entry->counters.blocks.temp_blks_written;
|
||||
|
||||
memcpy(&bufusage.blk_read_time, &entry->counters.blocks.instr_blk_read_time, sizeof(instr_time));
|
||||
memcpy(&bufusage.blk_write_time, &entry->counters.blocks.instr_blk_write_time, sizeof(instr_time));
|
||||
#if PG_VERSION_NUM < 170000
|
||||
memcpy(&bufusage.blk_read_time, &entry->counters.blocks.instr_shared_blk_read_time, sizeof(instr_time));
|
||||
memcpy(&bufusage.blk_write_time, &entry->counters.blocks.instr_shared_blk_write_time, sizeof(instr_time));
|
||||
#else
|
||||
memcpy(&bufusage.shared_blk_read_time, &entry->counters.blocks.instr_shared_blk_read_time, sizeof(instr_time));
|
||||
memcpy(&bufusage.shared_blk_write_time, &entry->counters.blocks.instr_shared_blk_write_time, sizeof(instr_time));
|
||||
memcpy(&bufusage.local_blk_read_time, &entry->counters.blocks.instr_local_blk_read_time, sizeof(instr_time));
|
||||
memcpy(&bufusage.local_blk_write_time, &entry->counters.blocks.instr_local_blk_write_time, sizeof(instr_time));
|
||||
#endif
|
||||
|
||||
#if PG_VERSION_NUM >= 150000
|
||||
memcpy(&bufusage.temp_blk_read_time, &entry->counters.blocks.instr_temp_blk_read_time, sizeof(instr_time));
|
||||
|
@ -1822,6 +1940,10 @@ pgsm_store(pgsmEntry * entry)
|
|||
memcpy(&jitusage.optimization_counter, &entry->counters.jitinfo.instr_optimization_counter, sizeof(instr_time));
|
||||
memcpy(&jitusage.emission_counter, &entry->counters.jitinfo.instr_emission_counter, sizeof(instr_time));
|
||||
|
||||
#if PG_VERSION_NUM >= 170000
|
||||
memcpy(&jitusage.deform_counter, &entry->counters.jitinfo.instr_deform_counter, sizeof(instr_time));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Acquire a share lock to start with. We'd have to acquire exclusive if
|
||||
* we need ot create the entry.
|
||||
|
@ -1979,6 +2101,13 @@ pg_stat_monitor_2_0(PG_FUNCTION_ARGS)
|
|||
return (Datum) 0;
|
||||
}
|
||||
|
||||
Datum
|
||||
pg_stat_monitor_2_1(PG_FUNCTION_ARGS)
|
||||
{
|
||||
pg_stat_monitor_internal(fcinfo, PGSM_V2_1, true);
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Legacy entry point for pg_stat_monitor() API versions 1.0
|
||||
*/
|
||||
|
@ -1999,7 +2128,7 @@ IsBucketValid(uint64 bucketid)
|
|||
|
||||
TimestampDifference(pgsm->bucket_start_time[bucketid], current_tz, &secs, µsecs);
|
||||
|
||||
if (secs > ((int64)pgsm_bucket_time * pgsm_max_buckets))
|
||||
if (secs > ((int64) pgsm_bucket_time * pgsm_max_buckets))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -2018,7 +2147,25 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
PGSM_HASH_SEQ_STATUS hstat;
|
||||
pgsmEntry *entry;
|
||||
pgsmSharedState *pgsm;
|
||||
int expected_columns = (api_version >= PGSM_V2_0) ? PG_STAT_MONITOR_COLS_V2_0 : PG_STAT_MONITOR_COLS_V1_0;
|
||||
|
||||
int expected_columns;
|
||||
|
||||
switch (api_version)
|
||||
{
|
||||
case PGSM_V1_0:
|
||||
expected_columns = PG_STAT_MONITOR_COLS_V1_0;
|
||||
break;
|
||||
case PGSM_V2_0:
|
||||
expected_columns = PG_STAT_MONITOR_COLS_V2_0;
|
||||
break;
|
||||
case PGSM_V2_1:
|
||||
expected_columns = PG_STAT_MONITOR_COLS_V2_1;
|
||||
break;
|
||||
default:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("[pg_stat_monitor] pg_stat_monitor_internal: Unknown API version")));
|
||||
}
|
||||
|
||||
/* Disallow old api usage */
|
||||
if (api_version < PGSM_V2_0)
|
||||
|
@ -2148,17 +2295,17 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
/* userid at column number 1 */
|
||||
values[i++] = ObjectIdGetDatum(userid);
|
||||
|
||||
/* userid at column number 1 */
|
||||
/* username at column number 2 */
|
||||
values[i++] = CStringGetTextDatum(entry->username);
|
||||
|
||||
/* dbid at column number 2 */
|
||||
/* dbid at column number 3 */
|
||||
values[i++] = ObjectIdGetDatum(dbid);
|
||||
|
||||
/* userid at column number 1 */
|
||||
/* datname at column number 4 */
|
||||
values[i++] = CStringGetTextDatum(entry->datname);
|
||||
|
||||
/*
|
||||
* ip address at column number 3, Superusers or members of
|
||||
* ip address at column number 5, Superusers or members of
|
||||
* pg_read_all_stats members are allowed
|
||||
*/
|
||||
if (is_allowed_role || userid == GetUserId())
|
||||
|
@ -2166,10 +2313,10 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
else
|
||||
nulls[i++] = true;
|
||||
|
||||
/* queryid at column number 4 */
|
||||
/* queryid at column number 6 */
|
||||
values[i++] = UInt64GetDatum(queryid);
|
||||
|
||||
/* planid at column number 5 */
|
||||
/* planid at column number 7 */
|
||||
if (planid)
|
||||
{
|
||||
values[i++] = UInt64GetDatum(planid);
|
||||
|
@ -2184,12 +2331,12 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
{
|
||||
char *enc;
|
||||
|
||||
/* query at column number 6 */
|
||||
/* query at column number 8 */
|
||||
enc = pg_any_to_server(query_txt, strlen(query_txt), GetDatabaseEncoding());
|
||||
values[i++] = CStringGetTextDatum(enc);
|
||||
if (enc != query_txt)
|
||||
pfree(enc);
|
||||
/* plan at column number 7 */
|
||||
/* plan at column number 9 */
|
||||
if (planid && tmp.planinfo.plan_text[0])
|
||||
values[i++] = CStringGetTextDatum(tmp.planinfo.plan_text);
|
||||
else
|
||||
|
@ -2197,25 +2344,26 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* query at column number 6 */
|
||||
/* query at column number 8 */
|
||||
nulls[i++] = true;
|
||||
/* plan at column number 7 */
|
||||
/* plan at column number 9 */
|
||||
nulls[i++] = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* query text at column number 6 */
|
||||
/* query text and plan at column number 8 and 9 */
|
||||
values[i++] = CStringGetTextDatum("<insufficient privilege>");
|
||||
values[i++] = CStringGetTextDatum("<insufficient privilege>");
|
||||
}
|
||||
|
||||
/* pgsm_query_id at column number 10 */
|
||||
if (pgsm_query_id)
|
||||
values[i++] = UInt64GetDatum(pgsm_query_id);
|
||||
else
|
||||
nulls[i++] = true;
|
||||
|
||||
/* parentid at column number 9 */
|
||||
/* parentid at column number 11 */
|
||||
if (tmp.info.parentid != UINT64CONST(0))
|
||||
{
|
||||
values[i++] = UInt64GetDatum(tmp.info.parentid);
|
||||
|
@ -2227,13 +2375,13 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
nulls[i++] = true;
|
||||
}
|
||||
|
||||
/* application_name at column number 10 */
|
||||
/* application_name at column number 15 */
|
||||
if (strlen(tmp.info.application_name) > 0)
|
||||
values[i++] = CStringGetTextDatum(tmp.info.application_name);
|
||||
else
|
||||
nulls[i++] = true;
|
||||
|
||||
/* relations at column number 10 */
|
||||
/* relations at column number 14 */
|
||||
if (tmp.info.num_relations > 0)
|
||||
{
|
||||
int j;
|
||||
|
@ -2262,28 +2410,28 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
else
|
||||
nulls[i++] = true;
|
||||
|
||||
/* cmd_type at column number 11 */
|
||||
/* cmd_type at column number 15 */
|
||||
if (tmp.info.cmd_type == CMD_NOTHING)
|
||||
nulls[i++] = true;
|
||||
else
|
||||
values[i++] = Int64GetDatumFast((int64) tmp.info.cmd_type);
|
||||
|
||||
/* elevel at column number 12 */
|
||||
/* elevel at column number 16 */
|
||||
values[i++] = Int64GetDatumFast(tmp.error.elevel);
|
||||
|
||||
/* sqlcode at column number 13 */
|
||||
/* sqlcode at column number 17 */
|
||||
if (strlen(tmp.error.sqlcode) == 0)
|
||||
nulls[i++] = true;
|
||||
else
|
||||
values[i++] = CStringGetTextDatum(tmp.error.sqlcode);
|
||||
|
||||
/* message at column number 14 */
|
||||
/* message at column number 18 */
|
||||
if (strlen(tmp.error.message) == 0)
|
||||
nulls[i++] = true;
|
||||
else
|
||||
values[i++] = CStringGetTextDatum(tmp.error.message);
|
||||
|
||||
/* bucket_start_time at column number 15 */
|
||||
/* bucket_start_time at column number 19 */
|
||||
values[i++] = TimestampTzGetDatum(pgsm->bucket_start_time[entry->key.bucket_id]);
|
||||
|
||||
if (tmp.calls.calls == 0)
|
||||
|
@ -2293,29 +2441,29 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
tmp.resp_calls[0]++;
|
||||
}
|
||||
|
||||
/* calls at column number 16 */
|
||||
/* calls at column number 20 */
|
||||
values[i++] = Int64GetDatumFast(tmp.calls.calls);
|
||||
|
||||
/* total_time at column number 17 */
|
||||
/* total_time at column number 21 */
|
||||
values[i++] = Float8GetDatumFast(tmp.time.total_time);
|
||||
|
||||
/* min_time at column number 18 */
|
||||
/* min_time at column number 22 */
|
||||
values[i++] = Float8GetDatumFast(tmp.time.min_time);
|
||||
|
||||
/* max_time at column number 19 */
|
||||
/* max_time at column number 23 */
|
||||
values[i++] = Float8GetDatumFast(tmp.time.max_time);
|
||||
|
||||
/* mean_time at column number 20 */
|
||||
/* mean_time at column number 24 */
|
||||
values[i++] = Float8GetDatumFast(tmp.time.mean_time);
|
||||
if (tmp.calls.calls > 1)
|
||||
stddev = sqrt(tmp.time.sum_var_time / tmp.calls.calls);
|
||||
else
|
||||
stddev = 0.0;
|
||||
|
||||
/* calls at column number 21 */
|
||||
/* stddev_exec_time at column number 25 */
|
||||
values[i++] = Float8GetDatumFast(stddev);
|
||||
|
||||
/* calls at column number 22 */
|
||||
/* rows at column number 26 */
|
||||
values[i++] = Int64GetDatumFast(tmp.calls.rows);
|
||||
|
||||
if (tmp.calls.calls == 0)
|
||||
|
@ -2325,29 +2473,29 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
tmp.resp_calls[0]++;
|
||||
}
|
||||
|
||||
/* calls at column number 23 */
|
||||
/* plans at column number 27 */
|
||||
values[i++] = Int64GetDatumFast(tmp.plancalls.calls);
|
||||
|
||||
/* total_time at column number 24 */
|
||||
/* total_plan_time at column number 28 */
|
||||
values[i++] = Float8GetDatumFast(tmp.plantime.total_time);
|
||||
|
||||
/* min_time at column number 25 */
|
||||
/* min_plan_time at column number 29 */
|
||||
values[i++] = Float8GetDatumFast(tmp.plantime.min_time);
|
||||
|
||||
/* max_time at column number 26 */
|
||||
/* max_plan_time at column number 30 */
|
||||
values[i++] = Float8GetDatumFast(tmp.plantime.max_time);
|
||||
|
||||
/* mean_time at column number 27 */
|
||||
/* mean_plan_time at column number 31 */
|
||||
values[i++] = Float8GetDatumFast(tmp.plantime.mean_time);
|
||||
if (tmp.plancalls.calls > 1)
|
||||
stddev = sqrt(tmp.plantime.sum_var_time / tmp.plancalls.calls);
|
||||
else
|
||||
stddev = 0.0;
|
||||
|
||||
/* calls at column number 28 */
|
||||
/* stddev_plan_time at column number 32 */
|
||||
values[i++] = Float8GetDatumFast(stddev);
|
||||
|
||||
/* blocks are from column number 29 - 40 */
|
||||
/* blocks are from column number 33 - 48 */
|
||||
values[i++] = Int64GetDatumFast(tmp.blocks.shared_blks_hit);
|
||||
values[i++] = Int64GetDatumFast(tmp.blocks.shared_blks_read);
|
||||
values[i++] = Int64GetDatumFast(tmp.blocks.shared_blks_dirtied);
|
||||
|
@ -2358,27 +2506,29 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
values[i++] = Int64GetDatumFast(tmp.blocks.local_blks_written);
|
||||
values[i++] = Int64GetDatumFast(tmp.blocks.temp_blks_read);
|
||||
values[i++] = Int64GetDatumFast(tmp.blocks.temp_blks_written);
|
||||
values[i++] = Float8GetDatumFast(tmp.blocks.blk_read_time);
|
||||
values[i++] = Float8GetDatumFast(tmp.blocks.blk_write_time);
|
||||
values[i++] = Float8GetDatumFast(tmp.blocks.shared_blk_read_time);
|
||||
values[i++] = Float8GetDatumFast(tmp.blocks.shared_blk_write_time);
|
||||
values[i++] = Float8GetDatumFast(tmp.blocks.local_blk_read_time);
|
||||
values[i++] = Float8GetDatumFast(tmp.blocks.local_blk_write_time);
|
||||
values[i++] = Float8GetDatumFast(tmp.blocks.temp_blk_read_time);
|
||||
values[i++] = Float8GetDatumFast(tmp.blocks.temp_blk_write_time);
|
||||
|
||||
/* resp_calls at column number 41 */
|
||||
/* resp_calls at column number 49 */
|
||||
values[i++] = IntArrayGetTextDatum(tmp.resp_calls, hist_bucket_count_total);
|
||||
|
||||
/* utime at column number 42 */
|
||||
/* cpu_user_time at column number 50 */
|
||||
values[i++] = Float8GetDatumFast(tmp.sysinfo.utime);
|
||||
|
||||
/* stime at column number 43 */
|
||||
/* cpu_sys_time at column number 51 */
|
||||
values[i++] = Float8GetDatumFast(tmp.sysinfo.stime);
|
||||
{
|
||||
char buf[256];
|
||||
Datum wal_bytes;
|
||||
|
||||
/* wal_records at column number 44 */
|
||||
/* wal_records at column number 52 */
|
||||
values[i++] = Int64GetDatumFast(tmp.walusage.wal_records);
|
||||
|
||||
/* wal_fpi at column number 45 */
|
||||
/* wal_fpi at column number 53 */
|
||||
values[i++] = Int64GetDatumFast(tmp.walusage.wal_fpi);
|
||||
|
||||
snprintf(buf, sizeof buf, UINT64_FORMAT, tmp.walusage.wal_bytes);
|
||||
|
@ -2388,15 +2538,16 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
CStringGetDatum(buf),
|
||||
ObjectIdGetDatum(0),
|
||||
Int32GetDatum(-1));
|
||||
/* wal_bytes at column number 46 */
|
||||
/* wal_bytes at column number 54 */
|
||||
values[i++] = wal_bytes;
|
||||
|
||||
/* application_name at column number 47 */
|
||||
/* application_name at column number 55 */
|
||||
if (strlen(tmp.info.comments) > 0)
|
||||
values[i++] = CStringGetTextDatum(tmp.info.comments);
|
||||
else
|
||||
nulls[i++] = true;
|
||||
|
||||
/* blocks are from column number 56 - 63 */
|
||||
values[i++] = Int64GetDatumFast(tmp.jitinfo.jit_functions);
|
||||
values[i++] = Float8GetDatumFast(tmp.jitinfo.jit_generation_time);
|
||||
values[i++] = Int64GetDatumFast(tmp.jitinfo.jit_inlining_count);
|
||||
|
@ -2405,8 +2556,18 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
values[i++] = Float8GetDatumFast(tmp.jitinfo.jit_optimization_time);
|
||||
values[i++] = Int64GetDatumFast(tmp.jitinfo.jit_emission_count);
|
||||
values[i++] = Float8GetDatumFast(tmp.jitinfo.jit_emission_time);
|
||||
values[i++] = Int64GetDatumFast(tmp.jitinfo.jit_deform_count);
|
||||
values[i++] = Float8GetDatumFast(tmp.jitinfo.jit_deform_time);
|
||||
}
|
||||
|
||||
/* at column number 64 */
|
||||
values[i++] = TimestampTzGetDatum(entry->stats_since);
|
||||
values[i++] = TimestampTzGetDatum(entry->minmax_stats_since);
|
||||
|
||||
/* toplevel at column number 66 */
|
||||
values[i++] = BoolGetDatum(toplevel);
|
||||
|
||||
/* bucket_done at column number 67 */
|
||||
values[i++] = BoolGetDatum(pg_atomic_read_u64(&pgsm->current_wbucket) != bucketid);
|
||||
|
||||
/* clean up and return the tuplestore */
|
||||
|
@ -2420,9 +2581,6 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
/* clean up and return the tuplestore */
|
||||
pgsm_hash_seq_term(&hstat);
|
||||
LWLockRelease(pgsm->lock);
|
||||
|
||||
|
||||
tuplestore_donestoring(tupstore);
|
||||
}
|
||||
|
||||
static uint64
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# pg_stat_monitor extension
|
||||
comment = 'The pg_stat_monitor is a PostgreSQL Query Performance Monitoring tool, based on PostgreSQL contrib module pg_stat_statements. pg_stat_monitor provides aggregated statistics, client information, plan details including plan, and histogram information.'
|
||||
default_version = '2.0'
|
||||
default_version = '2.1'
|
||||
module_pathname = '$libdir/pg_stat_monitor'
|
||||
relocatable = true
|
||||
|
|
|
@ -274,31 +274,33 @@ typedef struct Calls
|
|||
|
||||
typedef struct Blocks
|
||||
{
|
||||
int64 shared_blks_hit; /* # of shared buffer hits */
|
||||
int64 shared_blks_read; /* # of shared disk blocks read */
|
||||
int64 shared_blks_hit; /* # of shared buffer hits */
|
||||
int64 shared_blks_read; /* # of shared disk blocks read */
|
||||
int64 shared_blks_dirtied; /* # of shared disk blocks dirtied */
|
||||
int64 shared_blks_written; /* # of shared disk blocks written */
|
||||
int64 local_blks_hit; /* # of local buffer hits */
|
||||
int64 local_blks_read; /* # of local disk blocks read */
|
||||
int64 local_blks_dirtied; /* # of local disk blocks dirtied */
|
||||
int64 local_blks_written; /* # of local disk blocks written */
|
||||
int64 temp_blks_read; /* # of temp blocks read */
|
||||
int64 temp_blks_written; /* # of temp blocks written */
|
||||
double blk_read_time; /* time spent reading, in msec */
|
||||
double blk_write_time; /* time spent writing, in msec */
|
||||
|
||||
double temp_blk_read_time; /* time spent reading temp blocks, in msec */
|
||||
double temp_blk_write_time; /* time spent writing temp blocks, in
|
||||
* msec */
|
||||
int64 local_blks_hit; /* # of local buffer hits */
|
||||
int64 local_blks_read; /* # of local disk blocks read */
|
||||
int64 local_blks_dirtied; /* # of local disk blocks dirtied */
|
||||
int64 local_blks_written; /* # of local disk blocks written */
|
||||
int64 temp_blks_read; /* # of temp blocks read */
|
||||
int64 temp_blks_written; /* # of temp blocks written */
|
||||
double shared_blk_read_time; /* time spent reading shared blocks, in msec */
|
||||
double shared_blk_write_time; /* time spent writing shared blocks, in msec */
|
||||
double local_blk_read_time; /* time spent reading local blocks, in msec */
|
||||
double local_blk_write_time; /* time spent writing local blocks, in msec */
|
||||
double temp_blk_read_time; /* time spent reading temp blocks, in msec */
|
||||
double temp_blk_write_time; /* time spent writing temp blocks, in msec */
|
||||
|
||||
/*
|
||||
* Variables for local entry. The values to be passed to pgsm_update_entry
|
||||
* from pgsm_store.
|
||||
*/
|
||||
instr_time instr_blk_read_time; /* time spent reading blocks */
|
||||
instr_time instr_blk_write_time; /* time spent writing blocks */
|
||||
instr_time instr_temp_blk_read_time; /* time spent reading temp blocks */
|
||||
instr_time instr_temp_blk_write_time; /* time spent writing temp blocks */
|
||||
instr_time instr_shared_blk_read_time; /* time spent reading shared blocks */
|
||||
instr_time instr_shared_blk_write_time; /* time spent writing shared blocks */
|
||||
instr_time instr_local_blk_read_time; /* time spent reading local blocks */
|
||||
instr_time instr_local_blk_write_time; /* time spent writing local blocks */
|
||||
instr_time instr_temp_blk_read_time; /* time spent reading temp blocks */
|
||||
instr_time instr_temp_blk_write_time; /* time spent writing temp blocks */
|
||||
} Blocks;
|
||||
|
||||
typedef struct JitInfo
|
||||
|
@ -307,6 +309,9 @@ typedef struct JitInfo
|
|||
double jit_generation_time; /* total time to generate jit code */
|
||||
int64 jit_inlining_count; /* number of times inlining time has been
|
||||
* > 0 */
|
||||
double jit_deform_time; /* total time to deform tuples in jit code */
|
||||
int64 jit_deform_count; /* number of times deform time has been >
|
||||
* 0 */
|
||||
double jit_inlining_time; /* total time to inline jit code */
|
||||
int64 jit_optimization_count; /* number of times optimization time
|
||||
* has been > 0 */
|
||||
|
@ -321,6 +326,7 @@ typedef struct JitInfo
|
|||
*/
|
||||
instr_time instr_generation_counter; /* generation counter */
|
||||
instr_time instr_inlining_counter; /* inlining counter */
|
||||
instr_time instr_deform_counter; /* deform counter */
|
||||
instr_time instr_optimization_counter; /* optimization counter */
|
||||
instr_time instr_emission_counter; /* emission counter */
|
||||
} JitInfo;
|
||||
|
@ -370,6 +376,8 @@ typedef struct pgsmEntry
|
|||
char username[NAMEDATALEN]; /* user name */
|
||||
Counters counters; /* the statistics for this query */
|
||||
int encoding; /* query text encoding */
|
||||
TimestampTz stats_since; /* timestamp of entry allocation */
|
||||
TimestampTz minmax_stats_since; /* timestamp of last min/max values reset */
|
||||
slock_t mutex; /* protects the counters only */
|
||||
union
|
||||
{
|
||||
|
|
|
@ -24,9 +24,10 @@ SELECT routine_schema, routine_name, routine_type, data_type FROM information_sc
|
|||
public | pgsm_create_13_view | FUNCTION | integer
|
||||
public | pgsm_create_14_view | FUNCTION | integer
|
||||
public | pgsm_create_15_view | FUNCTION | integer
|
||||
public | pgsm_create_17_view | FUNCTION | integer
|
||||
public | pgsm_create_view | FUNCTION | integer
|
||||
public | range | FUNCTION | ARRAY
|
||||
(13 rows)
|
||||
(14 rows)
|
||||
|
||||
SET ROLE u1;
|
||||
SELECT routine_schema, routine_name, routine_type, data_type FROM information_schema.routines WHERE routine_schema = 'public' ORDER BY routine_name COLLATE "C";
|
||||
|
|
|
@ -24,9 +24,10 @@ SELECT routine_schema, routine_name, routine_type, data_type FROM information_sc
|
|||
public | pgsm_create_13_view | FUNCTION | integer
|
||||
public | pgsm_create_14_view | FUNCTION | integer
|
||||
public | pgsm_create_15_view | FUNCTION | integer
|
||||
public | pgsm_create_17_view | FUNCTION | integer
|
||||
public | pgsm_create_view | FUNCTION | integer
|
||||
public | range | FUNCTION | ARRAY
|
||||
(13 rows)
|
||||
(14 rows)
|
||||
|
||||
SET ROLE u1;
|
||||
SELECT routine_schema, routine_name, routine_type, data_type FROM information_schema.routines WHERE routine_schema = 'public' ORDER BY routine_name COLLATE "C";
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
--
|
||||
-- Statement level tracking
|
||||
--
|
||||
SELECT setting::integer < 140000 AS skip_test FROM pg_settings where name = 'server_version_num' \gset
|
||||
\if :skip_test
|
||||
\quit
|
|
@ -0,0 +1,326 @@
|
|||
--
|
||||
-- Statement level tracking
|
||||
--
|
||||
SELECT setting::integer < 140000 AS skip_test FROM pg_settings where name = 'server_version_num' \gset
|
||||
\if :skip_test
|
||||
\quit
|
||||
\endif
|
||||
CREATE EXTENSION pg_stat_monitor;
|
||||
SET pg_stat_monitor.pgsm_track_utility = TRUE;
|
||||
SET pg_stat_monitor.pgsm_normalized_query = TRUE;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- DO block - top-level tracking.
|
||||
CREATE TABLE stats_track_tab (x int);
|
||||
SET pg_stat_monitor.pgsm_track = 'top';
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
WHERE query LIKE '%DELETE%' ORDER BY query COLLATE "C", toplevel;
|
||||
toplevel | calls | query
|
||||
----------+-------+--------------------------------
|
||||
t | 1 | DELETE FROM stats_track_tab
|
||||
t | 1 | DO $$ +
|
||||
| | BEGIN +
|
||||
| | DELETE FROM stats_track_tab;+
|
||||
| | END; +
|
||||
| | $$ LANGUAGE plpgsql
|
||||
(2 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- DO block - all-level tracking.
|
||||
SET pg_stat_monitor.pgsm_track = 'all';
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END; $$;
|
||||
DO LANGUAGE plpgsql $$
|
||||
BEGIN
|
||||
-- this is a SELECT
|
||||
PERFORM 'hello world'::TEXT;
|
||||
END; $$;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
ORDER BY query COLLATE "C", toplevel;
|
||||
toplevel | calls | query
|
||||
----------+-------+----------------------------------------
|
||||
f | 1 | DELETE FROM stats_track_tab
|
||||
t | 1 | DELETE FROM stats_track_tab
|
||||
t | 1 | DO $$ +
|
||||
| | BEGIN +
|
||||
| | DELETE FROM stats_track_tab; +
|
||||
| | END; $$
|
||||
t | 1 | DO LANGUAGE plpgsql $$ +
|
||||
| | BEGIN +
|
||||
| | -- this is a SELECT +
|
||||
| | PERFORM 'hello world'::TEXT; +
|
||||
| | END; $$
|
||||
f | 1 | SELECT $1::TEXT
|
||||
t | 1 | SELECT pg_stat_monitor_reset()
|
||||
t | 1 | SET pg_stat_monitor.pgsm_track = 'all'
|
||||
(7 rows)
|
||||
|
||||
-- DO block - top-level tracking without utility.
|
||||
SET pg_stat_monitor.pgsm_track = 'top';
|
||||
SET pg_stat_monitor.pgsm_track_utility = FALSE;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END; $$;
|
||||
DO LANGUAGE plpgsql $$
|
||||
BEGIN
|
||||
-- this is a SELECT
|
||||
PERFORM 'hello world'::TEXT;
|
||||
END; $$;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
ORDER BY query COLLATE "C", toplevel;
|
||||
toplevel | calls | query
|
||||
----------+-------+--------------------------------
|
||||
t | 2 | DELETE FROM stats_track_tab
|
||||
t | 1 | SELECT $1::TEXT
|
||||
t | 1 | SELECT pg_stat_monitor_reset()
|
||||
(3 rows)
|
||||
|
||||
-- DO block - all-level tracking without utility.
|
||||
SET pg_stat_monitor.pgsm_track = 'all';
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END; $$;
|
||||
DO LANGUAGE plpgsql $$
|
||||
BEGIN
|
||||
-- this is a SELECT
|
||||
PERFORM 'hello world'::TEXT;
|
||||
END; $$;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
ORDER BY query COLLATE "C", toplevel;
|
||||
toplevel | calls | query
|
||||
----------+-------+--------------------------------
|
||||
t | 2 | DELETE FROM stats_track_tab
|
||||
t | 1 | SELECT $1::TEXT
|
||||
t | 1 | SELECT pg_stat_monitor_reset()
|
||||
(3 rows)
|
||||
|
||||
-- PL/pgSQL function - top-level tracking.
|
||||
SET pg_stat_monitor.pgsm_track = 'top';
|
||||
SET pg_stat_monitor.pgsm_track_utility = FALSE;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
CREATE FUNCTION PLUS_TWO(i INTEGER) RETURNS INTEGER AS $$
|
||||
DECLARE
|
||||
r INTEGER;
|
||||
BEGIN
|
||||
SELECT (i + 1 + 1.0)::INTEGER INTO r;
|
||||
RETURN r;
|
||||
END; $$ LANGUAGE plpgsql;
|
||||
SELECT PLUS_TWO(3);
|
||||
plus_two
|
||||
----------
|
||||
5
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_TWO(7);
|
||||
plus_two
|
||||
----------
|
||||
9
|
||||
(1 row)
|
||||
|
||||
-- SQL function --- use LIMIT to keep it from being inlined
|
||||
CREATE FUNCTION PLUS_ONE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT (i + 1.0)::INTEGER LIMIT 1 $$ LANGUAGE SQL;
|
||||
SELECT PLUS_ONE(8);
|
||||
plus_one
|
||||
----------
|
||||
9
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_ONE(10);
|
||||
plus_one
|
||||
----------
|
||||
11
|
||||
(1 row)
|
||||
|
||||
SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
calls | rows | query
|
||||
-------+------+--------------------------------
|
||||
2 | 2 | SELECT PLUS_ONE($1)
|
||||
2 | 2 | SELECT PLUS_TWO($1)
|
||||
1 | 1 | SELECT pg_stat_monitor_reset()
|
||||
(3 rows)
|
||||
|
||||
-- immutable SQL function --- can be executed at plan time
|
||||
CREATE FUNCTION PLUS_THREE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT i + 3 LIMIT 1 $$ IMMUTABLE LANGUAGE SQL;
|
||||
SELECT PLUS_THREE(8);
|
||||
plus_three
|
||||
------------
|
||||
11
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_THREE(10);
|
||||
plus_three
|
||||
------------
|
||||
13
|
||||
(1 row)
|
||||
|
||||
SELECT toplevel, calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
toplevel | calls | rows | query
|
||||
----------+-------+------+---------------------------------------------------------------------------
|
||||
t | 2 | 2 | SELECT PLUS_ONE($1)
|
||||
t | 2 | 2 | SELECT PLUS_THREE($1)
|
||||
t | 2 | 2 | SELECT PLUS_TWO($1)
|
||||
t | 1 | 3 | SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C"
|
||||
f | 2 | 2 | SELECT i + $2 LIMIT $3
|
||||
t | 1 | 1 | SELECT pg_stat_monitor_reset()
|
||||
(6 rows)
|
||||
|
||||
-- PL/pgSQL function - all-level tracking.
|
||||
SET pg_stat_monitor.pgsm_track = 'all';
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- we drop and recreate the functions to avoid any caching funnies
|
||||
DROP FUNCTION PLUS_ONE(INTEGER);
|
||||
DROP FUNCTION PLUS_TWO(INTEGER);
|
||||
DROP FUNCTION PLUS_THREE(INTEGER);
|
||||
-- PL/pgSQL function
|
||||
CREATE FUNCTION PLUS_TWO(i INTEGER) RETURNS INTEGER AS $$
|
||||
DECLARE
|
||||
r INTEGER;
|
||||
BEGIN
|
||||
SELECT (i + 1 + 1.0)::INTEGER INTO r;
|
||||
RETURN r;
|
||||
END; $$ LANGUAGE plpgsql;
|
||||
SELECT PLUS_TWO(-1);
|
||||
plus_two
|
||||
----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_TWO(2);
|
||||
plus_two
|
||||
----------
|
||||
4
|
||||
(1 row)
|
||||
|
||||
-- SQL function --- use LIMIT to keep it from being inlined
|
||||
CREATE FUNCTION PLUS_ONE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT (i + 1.0)::INTEGER LIMIT 1 $$ LANGUAGE SQL;
|
||||
SELECT PLUS_ONE(3);
|
||||
plus_one
|
||||
----------
|
||||
4
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_ONE(1);
|
||||
plus_one
|
||||
----------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
calls | rows | query
|
||||
-------+------+-----------------------------------
|
||||
2 | 2 | SELECT (i + $2 + $3)::INTEGER
|
||||
2 | 2 | SELECT (i + $2)::INTEGER LIMIT $3
|
||||
2 | 2 | SELECT PLUS_ONE($1)
|
||||
2 | 2 | SELECT PLUS_TWO($1)
|
||||
1 | 1 | SELECT pg_stat_monitor_reset()
|
||||
(5 rows)
|
||||
|
||||
-- immutable SQL function --- can be executed at plan time
|
||||
CREATE FUNCTION PLUS_THREE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT i + 3 LIMIT 1 $$ IMMUTABLE LANGUAGE SQL;
|
||||
SELECT PLUS_THREE(8);
|
||||
plus_three
|
||||
------------
|
||||
11
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_THREE(10);
|
||||
plus_three
|
||||
------------
|
||||
13
|
||||
(1 row)
|
||||
|
||||
SELECT toplevel, calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
toplevel | calls | rows | query
|
||||
----------+-------+------+---------------------------------------------------------------------------
|
||||
f | 2 | 2 | SELECT (i + $2 + $3)::INTEGER
|
||||
f | 2 | 2 | SELECT (i + $2)::INTEGER LIMIT $3
|
||||
t | 2 | 2 | SELECT PLUS_ONE($1)
|
||||
t | 2 | 2 | SELECT PLUS_THREE($1)
|
||||
t | 2 | 2 | SELECT PLUS_TWO($1)
|
||||
t | 1 | 5 | SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C"
|
||||
f | 2 | 2 | SELECT i + $2 LIMIT $3
|
||||
t | 1 | 1 | SELECT pg_stat_monitor_reset()
|
||||
(8 rows)
|
||||
|
||||
--
|
||||
-- pg_stat_monitor.pgsm_track = none
|
||||
--
|
||||
SET pg_stat_monitor.pgsm_track = 'none';
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT 1 AS "one";
|
||||
one
|
||||
-----
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT 1 + 1 AS "two";
|
||||
two
|
||||
-----
|
||||
2
|
||||
(1 row)
|
||||
|
||||
SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
calls | rows | query
|
||||
-------+------+-------
|
||||
(0 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
DROP EXTENSION pg_stat_monitor;
|
|
@ -0,0 +1,325 @@
|
|||
--
|
||||
-- Statement level tracking
|
||||
--
|
||||
SELECT setting::integer < 140000 AS skip_test FROM pg_settings where name = 'server_version_num' \gset
|
||||
\if :skip_test
|
||||
\quit
|
||||
\endif
|
||||
CREATE EXTENSION pg_stat_monitor;
|
||||
SET pg_stat_monitor.pgsm_track_utility = TRUE;
|
||||
SET pg_stat_monitor.pgsm_normalized_query = TRUE;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- DO block - top-level tracking.
|
||||
CREATE TABLE stats_track_tab (x int);
|
||||
SET pg_stat_monitor.pgsm_track = 'top';
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
WHERE query LIKE '%DELETE%' ORDER BY query COLLATE "C", toplevel;
|
||||
toplevel | calls | query
|
||||
----------+-------+--------------------------------
|
||||
t | 1 | DELETE FROM stats_track_tab
|
||||
t | 1 | DO $$ +
|
||||
| | BEGIN +
|
||||
| | DELETE FROM stats_track_tab;+
|
||||
| | END; +
|
||||
| | $$ LANGUAGE plpgsql
|
||||
(2 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- DO block - all-level tracking.
|
||||
SET pg_stat_monitor.pgsm_track = 'all';
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END; $$;
|
||||
DO LANGUAGE plpgsql $$
|
||||
BEGIN
|
||||
-- this is a SELECT
|
||||
PERFORM 'hello world'::TEXT;
|
||||
END; $$;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
ORDER BY query COLLATE "C", toplevel;
|
||||
toplevel | calls | query
|
||||
----------+-------+----------------------------------------
|
||||
f | 1 | DELETE FROM stats_track_tab
|
||||
t | 1 | DELETE FROM stats_track_tab
|
||||
t | 1 | DO $$ +
|
||||
| | BEGIN +
|
||||
| | DELETE FROM stats_track_tab; +
|
||||
| | END; $$
|
||||
t | 1 | DO LANGUAGE plpgsql $$ +
|
||||
| | BEGIN +
|
||||
| | -- this is a SELECT +
|
||||
| | PERFORM 'hello world'::TEXT; +
|
||||
| | END; $$
|
||||
f | 1 | SELECT $1::TEXT
|
||||
t | 1 | SELECT pg_stat_monitor_reset()
|
||||
t | 1 | SET pg_stat_monitor.pgsm_track = 'all'
|
||||
(7 rows)
|
||||
|
||||
-- DO block - top-level tracking without utility.
|
||||
SET pg_stat_monitor.pgsm_track = 'top';
|
||||
SET pg_stat_monitor.pgsm_track_utility = FALSE;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END; $$;
|
||||
DO LANGUAGE plpgsql $$
|
||||
BEGIN
|
||||
-- this is a SELECT
|
||||
PERFORM 'hello world'::TEXT;
|
||||
END; $$;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
ORDER BY query COLLATE "C", toplevel;
|
||||
toplevel | calls | query
|
||||
----------+-------+--------------------------------
|
||||
t | 1 | DELETE FROM stats_track_tab
|
||||
t | 1 | SELECT pg_stat_monitor_reset()
|
||||
(2 rows)
|
||||
|
||||
-- DO block - all-level tracking without utility.
|
||||
SET pg_stat_monitor.pgsm_track = 'all';
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END; $$;
|
||||
DO LANGUAGE plpgsql $$
|
||||
BEGIN
|
||||
-- this is a SELECT
|
||||
PERFORM 'hello world'::TEXT;
|
||||
END; $$;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
ORDER BY query COLLATE "C", toplevel;
|
||||
toplevel | calls | query
|
||||
----------+-------+--------------------------------
|
||||
f | 1 | DELETE FROM stats_track_tab
|
||||
t | 1 | DELETE FROM stats_track_tab
|
||||
f | 1 | SELECT $1::TEXT
|
||||
t | 1 | SELECT pg_stat_monitor_reset()
|
||||
(4 rows)
|
||||
|
||||
-- PL/pgSQL function - top-level tracking.
|
||||
SET pg_stat_monitor.pgsm_track = 'top';
|
||||
SET pg_stat_monitor.pgsm_track_utility = FALSE;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
CREATE FUNCTION PLUS_TWO(i INTEGER) RETURNS INTEGER AS $$
|
||||
DECLARE
|
||||
r INTEGER;
|
||||
BEGIN
|
||||
SELECT (i + 1 + 1.0)::INTEGER INTO r;
|
||||
RETURN r;
|
||||
END; $$ LANGUAGE plpgsql;
|
||||
SELECT PLUS_TWO(3);
|
||||
plus_two
|
||||
----------
|
||||
5
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_TWO(7);
|
||||
plus_two
|
||||
----------
|
||||
9
|
||||
(1 row)
|
||||
|
||||
-- SQL function --- use LIMIT to keep it from being inlined
|
||||
CREATE FUNCTION PLUS_ONE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT (i + 1.0)::INTEGER LIMIT 1 $$ LANGUAGE SQL;
|
||||
SELECT PLUS_ONE(8);
|
||||
plus_one
|
||||
----------
|
||||
9
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_ONE(10);
|
||||
plus_one
|
||||
----------
|
||||
11
|
||||
(1 row)
|
||||
|
||||
SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
calls | rows | query
|
||||
-------+------+--------------------------------
|
||||
2 | 2 | SELECT PLUS_ONE($1)
|
||||
2 | 2 | SELECT PLUS_TWO($1)
|
||||
1 | 1 | SELECT pg_stat_monitor_reset()
|
||||
(3 rows)
|
||||
|
||||
-- immutable SQL function --- can be executed at plan time
|
||||
CREATE FUNCTION PLUS_THREE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT i + 3 LIMIT 1 $$ IMMUTABLE LANGUAGE SQL;
|
||||
SELECT PLUS_THREE(8);
|
||||
plus_three
|
||||
------------
|
||||
11
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_THREE(10);
|
||||
plus_three
|
||||
------------
|
||||
13
|
||||
(1 row)
|
||||
|
||||
SELECT toplevel, calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
toplevel | calls | rows | query
|
||||
----------+-------+------+---------------------------------------------------------------------------
|
||||
t | 2 | 2 | SELECT PLUS_ONE($1)
|
||||
t | 2 | 2 | SELECT PLUS_THREE($1)
|
||||
t | 2 | 2 | SELECT PLUS_TWO($1)
|
||||
t | 1 | 3 | SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C"
|
||||
t | 1 | 1 | SELECT pg_stat_monitor_reset()
|
||||
(5 rows)
|
||||
|
||||
-- PL/pgSQL function - all-level tracking.
|
||||
SET pg_stat_monitor.pgsm_track = 'all';
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- we drop and recreate the functions to avoid any caching funnies
|
||||
DROP FUNCTION PLUS_ONE(INTEGER);
|
||||
DROP FUNCTION PLUS_TWO(INTEGER);
|
||||
DROP FUNCTION PLUS_THREE(INTEGER);
|
||||
-- PL/pgSQL function
|
||||
CREATE FUNCTION PLUS_TWO(i INTEGER) RETURNS INTEGER AS $$
|
||||
DECLARE
|
||||
r INTEGER;
|
||||
BEGIN
|
||||
SELECT (i + 1 + 1.0)::INTEGER INTO r;
|
||||
RETURN r;
|
||||
END; $$ LANGUAGE plpgsql;
|
||||
SELECT PLUS_TWO(-1);
|
||||
plus_two
|
||||
----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_TWO(2);
|
||||
plus_two
|
||||
----------
|
||||
4
|
||||
(1 row)
|
||||
|
||||
-- SQL function --- use LIMIT to keep it from being inlined
|
||||
CREATE FUNCTION PLUS_ONE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT (i + 1.0)::INTEGER LIMIT 1 $$ LANGUAGE SQL;
|
||||
SELECT PLUS_ONE(3);
|
||||
plus_one
|
||||
----------
|
||||
4
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_ONE(1);
|
||||
plus_one
|
||||
----------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
calls | rows | query
|
||||
-------+------+-----------------------------------
|
||||
2 | 2 | SELECT (i + $2 + $3)::INTEGER
|
||||
2 | 2 | SELECT (i + $2)::INTEGER LIMIT $3
|
||||
2 | 2 | SELECT PLUS_ONE($1)
|
||||
2 | 2 | SELECT PLUS_TWO($1)
|
||||
1 | 1 | SELECT pg_stat_monitor_reset()
|
||||
(5 rows)
|
||||
|
||||
-- immutable SQL function --- can be executed at plan time
|
||||
CREATE FUNCTION PLUS_THREE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT i + 3 LIMIT 1 $$ IMMUTABLE LANGUAGE SQL;
|
||||
SELECT PLUS_THREE(8);
|
||||
plus_three
|
||||
------------
|
||||
11
|
||||
(1 row)
|
||||
|
||||
SELECT PLUS_THREE(10);
|
||||
plus_three
|
||||
------------
|
||||
13
|
||||
(1 row)
|
||||
|
||||
SELECT toplevel, calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
toplevel | calls | rows | query
|
||||
----------+-------+------+---------------------------------------------------------------------------
|
||||
f | 2 | 2 | SELECT (i + $2 + $3)::INTEGER
|
||||
f | 2 | 2 | SELECT (i + $2)::INTEGER LIMIT $3
|
||||
t | 2 | 2 | SELECT PLUS_ONE($1)
|
||||
t | 2 | 2 | SELECT PLUS_THREE($1)
|
||||
t | 2 | 2 | SELECT PLUS_TWO($1)
|
||||
t | 1 | 5 | SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C"
|
||||
f | 2 | 2 | SELECT i + $2 LIMIT $3
|
||||
t | 1 | 1 | SELECT pg_stat_monitor_reset()
|
||||
(8 rows)
|
||||
|
||||
--
|
||||
-- pg_stat_monitor.pgsm_track = none
|
||||
--
|
||||
SET pg_stat_monitor.pgsm_track = 'none';
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT 1 AS "one";
|
||||
one
|
||||
-----
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT 1 + 1 AS "two";
|
||||
two
|
||||
-----
|
||||
2
|
||||
(1 row)
|
||||
|
||||
SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
calls | rows | query
|
||||
-------+------+-------
|
||||
(0 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
DROP EXTENSION pg_stat_monitor;
|
|
@ -0,0 +1,115 @@
|
|||
CREATE EXTENSION pg_stat_monitor;
|
||||
CREATE DATABASE db1;
|
||||
CREATE DATABASE db2;
|
||||
\c db1
|
||||
CREATE TABLE t1 (a int);
|
||||
CREATE TABLE t2 (b int);
|
||||
CREATE FUNCTION add(integer, integer) RETURNS integer
|
||||
AS 'select $1 + $2;'
|
||||
LANGUAGE SQL
|
||||
IMMUTABLE
|
||||
RETURNS NULL ON NULL INPUT;
|
||||
\c db2
|
||||
CREATE TABLE t1 (a int);
|
||||
CREATE TABLE t3 (c int);
|
||||
CREATE FUNCTION add(integer, integer) RETURNS integer
|
||||
AS 'select $1 + $2;'
|
||||
LANGUAGE SQL
|
||||
IMMUTABLE
|
||||
RETURNS NULL ON NULL INPUT;
|
||||
\c contrib_regression
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
\c db1
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
---
|
||||
(0 rows)
|
||||
|
||||
SELECT *, ADD(1, 2) FROM t1;
|
||||
a | add
|
||||
---+-----
|
||||
(0 rows)
|
||||
|
||||
SELECT * FROM t2;
|
||||
b
|
||||
---
|
||||
(0 rows)
|
||||
|
||||
-- Check that spaces and comments do not generate a different pgsm_query_id
|
||||
SELECT * FROM t2 --WHATEVER;
|
||||
;
|
||||
b
|
||||
---
|
||||
(0 rows)
|
||||
|
||||
SELECT * FROM t2 /* ...
|
||||
...
|
||||
More comments to check for spaces.
|
||||
*/
|
||||
;
|
||||
b
|
||||
---
|
||||
(0 rows)
|
||||
|
||||
\c db2
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
---
|
||||
(0 rows)
|
||||
|
||||
SELECT *, ADD(1, 2) FROM t1;
|
||||
a | add
|
||||
---+-----
|
||||
(0 rows)
|
||||
|
||||
set pg_stat_monitor.pgsm_enable_pgsm_query_id = off;
|
||||
SELECT * FROM t3;
|
||||
c
|
||||
---
|
||||
(0 rows)
|
||||
|
||||
set pg_stat_monitor.pgsm_enable_pgsm_query_id = on;
|
||||
SELECT * FROM t3 where c = 20;
|
||||
c
|
||||
---
|
||||
(0 rows)
|
||||
|
||||
\c contrib_regression
|
||||
SELECT datname, pgsm_query_id, query, calls FROM pg_stat_monitor ORDER BY pgsm_query_id, query, datname;
|
||||
datname | pgsm_query_id | query | calls
|
||||
--------------------+---------------------+-----------------------------------------------------+-------
|
||||
contrib_regression | 689150021118383254 | SELECT pg_stat_monitor_reset() | 1
|
||||
db1 | 1897482803466821995 | SELECT * FROM t2 | 3
|
||||
db1 | 1988437669671417938 | SELECT * FROM t1 | 1
|
||||
db2 | 1988437669671417938 | SELECT * FROM t1 | 1
|
||||
db2 | 6220142855706866455 | set pg_stat_monitor.pgsm_enable_pgsm_query_id = on | 1
|
||||
db2 | 6633979598391393345 | SELECT * FROM t3 where c = 20 | 1
|
||||
db1 | 8140395000078788481 | SELECT *, ADD(1, 2) FROM t1 | 1
|
||||
db2 | 8140395000078788481 | SELECT *, ADD(1, 2) FROM t1 | 1
|
||||
db2 | | SELECT * FROM t3 | 1
|
||||
db2 | | set pg_stat_monitor.pgsm_enable_pgsm_query_id = off | 1
|
||||
(10 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
\c db1
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP FUNCTION ADD;
|
||||
\c db2
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t3;
|
||||
DROP FUNCTION ADD;
|
||||
\c contrib_regression
|
||||
DROP DATABASE db1;
|
||||
DROP DATABASE db2;
|
||||
DROP EXTENSION pg_stat_monitor;
|
|
@ -2,7 +2,7 @@ CREATE EXTENSION pg_stat_monitor;
|
|||
SELECT pg_stat_monitor_version();
|
||||
pg_stat_monitor_version
|
||||
-------------------------
|
||||
2.0.4
|
||||
2.1.0
|
||||
(1 row)
|
||||
|
||||
DROP EXTENSION pg_stat_monitor;
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
--
|
||||
-- Statement level tracking
|
||||
--
|
||||
|
||||
SELECT setting::integer < 140000 AS skip_test FROM pg_settings where name = 'server_version_num' \gset
|
||||
\if :skip_test
|
||||
\quit
|
||||
\endif
|
||||
|
||||
CREATE EXTENSION pg_stat_monitor;
|
||||
SET pg_stat_monitor.pgsm_track_utility = TRUE;
|
||||
SET pg_stat_monitor.pgsm_normalized_query = TRUE;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
||||
-- DO block - top-level tracking.
|
||||
CREATE TABLE stats_track_tab (x int);
|
||||
SET pg_stat_monitor.pgsm_track = 'top';
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
WHERE query LIKE '%DELETE%' ORDER BY query COLLATE "C", toplevel;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
||||
-- DO block - all-level tracking.
|
||||
SET pg_stat_monitor.pgsm_track = 'all';
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END; $$;
|
||||
DO LANGUAGE plpgsql $$
|
||||
BEGIN
|
||||
-- this is a SELECT
|
||||
PERFORM 'hello world'::TEXT;
|
||||
END; $$;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
ORDER BY query COLLATE "C", toplevel;
|
||||
|
||||
-- DO block - top-level tracking without utility.
|
||||
SET pg_stat_monitor.pgsm_track = 'top';
|
||||
SET pg_stat_monitor.pgsm_track_utility = FALSE;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END; $$;
|
||||
DO LANGUAGE plpgsql $$
|
||||
BEGIN
|
||||
-- this is a SELECT
|
||||
PERFORM 'hello world'::TEXT;
|
||||
END; $$;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
ORDER BY query COLLATE "C", toplevel;
|
||||
|
||||
-- DO block - all-level tracking without utility.
|
||||
SET pg_stat_monitor.pgsm_track = 'all';
|
||||
SELECT pg_stat_monitor_reset();
|
||||
DELETE FROM stats_track_tab;
|
||||
DO $$
|
||||
BEGIN
|
||||
DELETE FROM stats_track_tab;
|
||||
END; $$;
|
||||
DO LANGUAGE plpgsql $$
|
||||
BEGIN
|
||||
-- this is a SELECT
|
||||
PERFORM 'hello world'::TEXT;
|
||||
END; $$;
|
||||
SELECT toplevel, calls, query FROM pg_stat_monitor
|
||||
ORDER BY query COLLATE "C", toplevel;
|
||||
|
||||
-- PL/pgSQL function - top-level tracking.
|
||||
SET pg_stat_monitor.pgsm_track = 'top';
|
||||
SET pg_stat_monitor.pgsm_track_utility = FALSE;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
CREATE FUNCTION PLUS_TWO(i INTEGER) RETURNS INTEGER AS $$
|
||||
DECLARE
|
||||
r INTEGER;
|
||||
BEGIN
|
||||
SELECT (i + 1 + 1.0)::INTEGER INTO r;
|
||||
RETURN r;
|
||||
END; $$ LANGUAGE plpgsql;
|
||||
|
||||
SELECT PLUS_TWO(3);
|
||||
SELECT PLUS_TWO(7);
|
||||
|
||||
-- SQL function --- use LIMIT to keep it from being inlined
|
||||
CREATE FUNCTION PLUS_ONE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT (i + 1.0)::INTEGER LIMIT 1 $$ LANGUAGE SQL;
|
||||
|
||||
SELECT PLUS_ONE(8);
|
||||
SELECT PLUS_ONE(10);
|
||||
|
||||
SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
|
||||
-- immutable SQL function --- can be executed at plan time
|
||||
CREATE FUNCTION PLUS_THREE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT i + 3 LIMIT 1 $$ IMMUTABLE LANGUAGE SQL;
|
||||
|
||||
SELECT PLUS_THREE(8);
|
||||
SELECT PLUS_THREE(10);
|
||||
|
||||
SELECT toplevel, calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
|
||||
-- PL/pgSQL function - all-level tracking.
|
||||
SET pg_stat_monitor.pgsm_track = 'all';
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
||||
-- we drop and recreate the functions to avoid any caching funnies
|
||||
DROP FUNCTION PLUS_ONE(INTEGER);
|
||||
DROP FUNCTION PLUS_TWO(INTEGER);
|
||||
DROP FUNCTION PLUS_THREE(INTEGER);
|
||||
|
||||
-- PL/pgSQL function
|
||||
CREATE FUNCTION PLUS_TWO(i INTEGER) RETURNS INTEGER AS $$
|
||||
DECLARE
|
||||
r INTEGER;
|
||||
BEGIN
|
||||
SELECT (i + 1 + 1.0)::INTEGER INTO r;
|
||||
RETURN r;
|
||||
END; $$ LANGUAGE plpgsql;
|
||||
|
||||
SELECT PLUS_TWO(-1);
|
||||
SELECT PLUS_TWO(2);
|
||||
|
||||
-- SQL function --- use LIMIT to keep it from being inlined
|
||||
CREATE FUNCTION PLUS_ONE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT (i + 1.0)::INTEGER LIMIT 1 $$ LANGUAGE SQL;
|
||||
|
||||
SELECT PLUS_ONE(3);
|
||||
SELECT PLUS_ONE(1);
|
||||
|
||||
SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
|
||||
-- immutable SQL function --- can be executed at plan time
|
||||
CREATE FUNCTION PLUS_THREE(i INTEGER) RETURNS INTEGER AS
|
||||
$$ SELECT i + 3 LIMIT 1 $$ IMMUTABLE LANGUAGE SQL;
|
||||
|
||||
SELECT PLUS_THREE(8);
|
||||
SELECT PLUS_THREE(10);
|
||||
|
||||
SELECT toplevel, calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
|
||||
--
|
||||
-- pg_stat_monitor.pgsm_track = none
|
||||
--
|
||||
SET pg_stat_monitor.pgsm_track = 'none';
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
||||
SELECT 1 AS "one";
|
||||
SELECT 1 + 1 AS "two";
|
||||
|
||||
SELECT calls, rows, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
||||
DROP EXTENSION pg_stat_monitor;
|
|
@ -22,7 +22,22 @@ print $conf "shared_preload_libraries = 'pg_stat_monitor'\n";
|
|||
close $conf;
|
||||
|
||||
# Dictionary for expected PGSM columns names on different PG server versions
|
||||
my %pg_versions_pgsm_columns = ( 16 => "application_name,blk_read_time," .
|
||||
my %pg_versions_pgsm_columns = ( 17 => "application_name,".
|
||||
"bucket,bucket_done,bucket_start_time,calls," .
|
||||
"client_ip,cmd_type,cmd_type_text,comments,cpu_sys_time,cpu_user_time," .
|
||||
"datname,dbid,elevel,jit_deform_count,jit_deform_time," .
|
||||
"jit_emission_count,jit_emission_time,jit_functions,jit_generation_time," .
|
||||
"jit_inlining_count,jit_inlining_time,jit_optimization_count,jit_optimization_time," .
|
||||
"local_blk_read_time,local_blk_write_time,local_blks_dirtied,local_blks_hit,".
|
||||
"local_blks_read,local_blks_written,max_exec_time,max_plan_time,mean_exec_time," .
|
||||
"mean_plan_time,message,min_exec_time,min_plan_time,minmax_stats_since," .
|
||||
"pgsm_query_id,planid,plans,query,query_plan,queryid,relations,resp_calls,rows," .
|
||||
"shared_blk_read_time,shared_blk_write_time,shared_blks_dirtied," .
|
||||
"shared_blks_hit,shared_blks_read,shared_blks_written,sqlcode,stats_since," .
|
||||
"stddev_exec_time,stddev_plan_time,temp_blk_read_time,temp_blk_write_time," .
|
||||
"temp_blks_read,temp_blks_written,top_query,top_queryid,toplevel," .
|
||||
"total_exec_time,total_plan_time,userid,username,wal_bytes,wal_fpi,wal_records",
|
||||
16 => "application_name,blk_read_time," .
|
||||
"blk_write_time,bucket,bucket_done,bucket_start_time,calls," .
|
||||
"client_ip,cmd_type,cmd_type_text,comments,cpu_sys_time,cpu_user_time," .
|
||||
"datname,dbid,elevel,jit_emission_count,jit_emission_time,jit_functions," .
|
||||
|
|
|
@ -35,6 +35,15 @@ $node->append_conf('postgresql.conf', "pg_stat_monitor.pgsm_normalized_query = y
|
|||
my $rt_value = $node->start;
|
||||
ok($rt_value == 1, "Start Server");
|
||||
|
||||
my $col_shared_blk_read_time = "shared_blk_read_time";
|
||||
my $col_shared_blk_write_time = "shared_blk_write_time";
|
||||
|
||||
if ($PGSM::PG_MAJOR_VERSION <= 16)
|
||||
{
|
||||
$col_shared_blk_read_time = "blk_read_time";
|
||||
$col_shared_blk_write_time = "blk_write_time";
|
||||
}
|
||||
|
||||
# CREATE EXTENSION and change out file permissions
|
||||
my ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'CREATE EXTENSION pg_stat_statements;', extra_params => ['-a']);
|
||||
ok($cmdret == 0, "CREATE PGSS EXTENSION");
|
||||
|
@ -78,10 +87,10 @@ ok($cmdret == 0, "Run pgbench");
|
|||
ok($cmdret == 0, "Run pg_sleep for 2 seconds ");
|
||||
PGSM::append_to_file($stdout);
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT substr(query,0,30),calls, rows, ROUND(total_exec_time::numeric,4) AS total_exec_time, ROUND(min_exec_time::numeric,4) AS min_exec_time, ROUND(max_exec_time::numeric,4) AS max_exec_time, ROUND(mean_exec_time::numeric,4) AS mean_exec_time, ROUND(stddev_exec_time::numeric,4) AS stddev_exec_time, ROUND(blk_read_time::numeric,4) AS blk_read_time, ROUND(blk_write_time::numeric,4) AS blk_write_time FROM pg_stat_statements WHERE query LIKE \'%bench%\' ORDER BY query,calls DESC;', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT substr(query,0,30),calls, rows, ROUND(total_exec_time::numeric,4) AS total_exec_time, ROUND(min_exec_time::numeric,4) AS min_exec_time, ROUND(max_exec_time::numeric,4) AS max_exec_time, ROUND(mean_exec_time::numeric,4) AS mean_exec_time, ROUND(stddev_exec_time::numeric,4) AS stddev_exec_time, ROUND(${col_shared_blk_read_time}::numeric,4) AS ${col_shared_blk_read_time}, ROUND(${col_shared_blk_write_time}::numeric,4) AS ${col_shared_blk_write_time} FROM pg_stat_statements WHERE query LIKE '%bench%' ORDER BY query,calls DESC;", extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
PGSM::append_to_debug_file($stdout);
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT bucket, bucket_start_time, queryid, substr(query,0,30) AS query, calls, rows, total_exec_time, min_exec_time, max_exec_time, mean_exec_time, stddev_exec_time, ROUND(blk_read_time::numeric,4) AS blk_read_time, ROUND(blk_write_time::numeric,4) AS blk_write_time, cpu_user_time, cpu_sys_time FROM pg_stat_monitor WHERE query LIKE \'%bench%\' ORDER BY query,calls DESC;', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT bucket, bucket_start_time, queryid, substr(query,0,30) AS query, calls, rows, total_exec_time, min_exec_time, max_exec_time, mean_exec_time, stddev_exec_time, ROUND(${col_shared_blk_read_time}::numeric,4) AS ${col_shared_blk_read_time}, ROUND(${col_shared_blk_write_time}::numeric,4) AS ${col_shared_blk_write_time}, cpu_user_time, cpu_sys_time FROM pg_stat_monitor WHERE query LIKE '%bench%' ORDER BY query,calls DESC;", extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
PGSM::append_to_debug_file($stdout);
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT substr(query,0,30) AS query,calls,rows,wal_records,wal_fpi,wal_bytes FROM pg_stat_statements WHERE query LIKE \'%bench%\' ORDER BY query,calls;', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
|
@ -160,13 +169,13 @@ is($stdout,'t',"Compare: mean_exec_time is equal.");
|
|||
trim($stdout);
|
||||
is($stdout,'t',"Compare: stddev_exec_time is equal.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(ROUND(PGSM.blk_read_time::numeric,4)) = SUM(ROUND(PGSS.blk_read_time::numeric,4)) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT SUM(ROUND(PGSM.${col_shared_blk_read_time}::numeric,4)) = SUM(ROUND(PGSS.${col_shared_blk_read_time}::numeric,4)) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;", extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Compare: blk_read_time is equal.");
|
||||
is($stdout,'t',"Compare: ${col_shared_blk_read_time} is equal.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(ROUND(PGSM.blk_write_time::numeric,4)) = SUM(ROUND(PGSS.blk_write_time::numeric,4)) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT SUM(ROUND(PGSM.${col_shared_blk_write_time}::numeric,4)) = SUM(ROUND(PGSS.${col_shared_blk_write_time}::numeric,4)) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;", extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Compare: blk_write_time is equal.");
|
||||
is($stdout,'t',"Compare: ${col_shared_blk_write_time} is equal.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.wal_records) = SUM(PGSS.wal_records) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
|
@ -209,13 +218,13 @@ is($stdout,'t',"Compare: mean_exec_time is equal.");
|
|||
trim($stdout);
|
||||
is($stdout,'t',"Compare: stddev_exec_time is equal.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(ROUND(PGSM.blk_read_time::numeric,4)) = SUM(ROUND(PGSS.blk_read_time::numeric,4)) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%SELECT abalance FROM pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT SUM(ROUND(PGSM.${col_shared_blk_read_time}::numeric,4)) = SUM(ROUND(PGSS.${col_shared_blk_read_time}::numeric,4)) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%SELECT abalance FROM pgbench_accounts%\' GROUP BY PGSM.query;", extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Compare: blk_read_time is equal.");
|
||||
is($stdout,'t',"Compare: ${col_shared_blk_read_time} is equal.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(ROUND(PGSM.blk_write_time::numeric,4)) = SUM(ROUND(PGSS.blk_write_time::numeric,4)) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%SELECT abalance FROM pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT SUM(ROUND(PGSM.${col_shared_blk_write_time}::numeric,4)) = SUM(ROUND(PGSS.${col_shared_blk_write_time}::numeric,4)) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%SELECT abalance FROM pgbench_accounts%\' GROUP BY PGSM.query;", extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Compare: blk_write_time is equal.");
|
||||
is($stdout,'t',"Compare: ${col_shared_blk_write_time} is equal.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.wal_records) = SUM(PGSS.wal_records) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%SELECT abalance FROM pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
|
@ -258,9 +267,9 @@ is($stdout,'t',"Compare: mean_exec_time is equal.");
|
|||
trim($stdout);
|
||||
is($stdout,'t',"Compare: stddev_exec_time is equal.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(ROUND(PGSM.blk_write_time::numeric,4)) = SUM(ROUND(PGSS.blk_write_time::numeric,4)) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%UPDATE pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT SUM(ROUND(PGSM.${col_shared_blk_write_time}::numeric,4)) = SUM(ROUND(PGSS.${col_shared_blk_write_time}::numeric,4)) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%UPDATE pgbench_accounts%\' GROUP BY PGSM.query;", extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Compare: blk_write_time is equal.");
|
||||
is($stdout,'t',"Compare: ${col_shared_blk_write_time} is equal.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.wal_records) = SUM(PGSS.wal_records) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%UPDATE pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
|
|
|
@ -35,6 +35,15 @@ $node->append_conf('postgresql.conf', "pg_stat_monitor.pgsm_normalized_query = y
|
|||
my $rt_value = $node->start;
|
||||
ok($rt_value == 1, "Start Server");
|
||||
|
||||
my $col_shared_blk_read_time = "shared_blk_read_time";
|
||||
my $col_shared_blk_write_time = "shared_blk_write_time";
|
||||
|
||||
if ($PGSM::PG_MAJOR_VERSION <= 16)
|
||||
{
|
||||
$col_shared_blk_read_time = "blk_read_time";
|
||||
$col_shared_blk_write_time = "blk_write_time";
|
||||
}
|
||||
|
||||
# CREATE EXTENSION and change out file permissions
|
||||
my ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'CREATE EXTENSION pg_stat_statements;', extra_params => ['-a']);
|
||||
ok($cmdret == 0, "CREATE PGSS EXTENSION");
|
||||
|
@ -86,7 +95,7 @@ PGSM::append_to_debug_file($stdout);
|
|||
PGSM::append_to_debug_file($stdout);
|
||||
PGSM::append_to_debug_file("--------");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT substr(query,0,130) AS query, calls, rows, shared_blks_hit, shared_blks_read, shared_blks_dirtied, shared_blks_written, blk_read_time, blk_write_time FROM pg_stat_monitor WHERE query LIKE \'%bench%\' ORDER BY query,calls DESC;', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT substr(query,0,130) AS query, calls, rows, shared_blks_hit, shared_blks_read, shared_blks_dirtied, shared_blks_written, ${col_shared_blk_read_time}, ${col_shared_blk_write_time} FROM pg_stat_monitor WHERE query LIKE '%bench%' ORDER BY query,calls DESC;", extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
PGSM::append_to_debug_file($stdout);
|
||||
|
||||
# Compare values for query 'DELETE FROM pgbench_accounts WHERE $1 = $2'
|
||||
|
@ -106,13 +115,13 @@ is($stdout,'t',"Check: shared_blks_dirtied should not be 0.");
|
|||
trim($stdout);
|
||||
is($stdout,'t',"Check: shared_blks_written should not be 0.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres','SELECT SUM(PGSM.blk_read_time) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%DELETE FROM pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres',"SELECT SUM(PGSM.${col_shared_blk_read_time}) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE '%DELETE FROM pgbench_accounts%' GROUP BY PGSM.query;", extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: blk_read_time should not be 0.");
|
||||
is($stdout,'t',"Check: ${col_shared_blk_read_time} should not be 0.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres','SELECT SUM(PGSM.blk_write_time) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%DELETE FROM pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres',"SELECT SUM(PGSM.${col_shared_blk_write_time}) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE '%DELETE FROM pgbench_accounts%' GROUP BY PGSM.query;", extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: blk_write_time should not be 0.");
|
||||
is($stdout,'t',"Check: ${col_shared_blk_write_time} should not be 0.");
|
||||
|
||||
# Compare values for query 'INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP)'
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres','SELECT SUM(PGSM.shared_blks_hit) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
|
@ -127,9 +136,9 @@ is($stdout,'t',"Check: shared_blks_dirtied should not be 0.");
|
|||
trim($stdout);
|
||||
is($stdout,'t',"Check: shared_blks_written should not be 0.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres','SELECT SUM(PGSM.blk_write_time) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres',"SELECT SUM(PGSM.${col_shared_blk_write_time}) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE '%INSERT INTO pgbench_history%' GROUP BY PGSM.query;", extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: blk_write_time should not be 0.");
|
||||
is($stdout,'t',"Check: ${col_shared_blk_write_time} should not be 0.");
|
||||
|
||||
# Compare values for query 'UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2'
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres','SELECT SUM(PGSM.shared_blks_hit) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%UPDATE pgbench_accounts SET abalance%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
|
@ -148,13 +157,13 @@ is($stdout,'t',"Check: shared_blks_dirtied should not be 0.");
|
|||
trim($stdout);
|
||||
is($stdout,'t',"Check: shared_blks_written should not be 0.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres','SELECT SUM(PGSM.blk_read_time) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%UPDATE pgbench_accounts SET abalance%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT SUM(PGSM.${col_shared_blk_read_time}) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE '%UPDATE pgbench_accounts SET abalance%' GROUP BY PGSM.query;", extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: blk_read_time should not be 0.");
|
||||
is($stdout,'t',"Check: ${col_shared_blk_read_time} should not be 0.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres','SELECT SUM(PGSM.blk_write_time) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%UPDATE pgbench_accounts SET abalance%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres',"SELECT SUM(PGSM.${col_shared_blk_write_time}) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE '%UPDATE pgbench_accounts SET abalance%' GROUP BY PGSM.query;", extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: blk_write_time should not be 0.");
|
||||
is($stdout,'t',"Check: ${col_shared_blk_write_time} should not be 0.");
|
||||
|
||||
# DROP EXTENSION
|
||||
$stdout = $node->safe_psql('postgres', 'DROP EXTENSION pg_stat_monitor;', extra_params => ['-a']);
|
||||
|
|
|
@ -70,10 +70,26 @@ is($stdout,'t',"Check: local_blks_hit should not be 0.");
|
|||
trim($stdout);
|
||||
is($stdout,'t',"Check: local_blks_dirtied should not be 0.");
|
||||
|
||||
if ($PGSM::PG_MAJOR_VERSION >= 17)
|
||||
{
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.local_blk_write_time) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%INSERT INTO t1%\'', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: local_blk_write_time should not be 0.");
|
||||
}
|
||||
|
||||
|
||||
# Compare values for query 'SELECT * FROM t1'
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT PGSM.local_blks_hit != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%FROM t1%\';', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: shared_blks_hit should not be 0.");
|
||||
is($stdout,'t',"Check: local_blks_hit should not be 0.");
|
||||
|
||||
# TODO: Find a way how to bypass cache and get real block reads
|
||||
# if ($PGSM::PG_MAJOR_VERSION >= 17)
|
||||
# {
|
||||
# ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.local_blk_read_time) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%FROM t1%\';', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
# trim($stdout);
|
||||
# is($stdout,'t',"Check: local_blk_read_time should not be 0.");
|
||||
# }
|
||||
|
||||
# DROP EXTENSION
|
||||
$stdout = $node->safe_psql('postgres', 'DROP EXTENSION pg_stat_monitor;', extra_params => ['-a']);
|
||||
|
|
|
@ -85,11 +85,22 @@ PGSM::append_to_debug_file($stdout);
|
|||
# Compare values for query 'SELECT * FROM t1'
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT PGSM.temp_blks_read != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%FROM t1%\';', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: shared_blks_hit should not be 0.");
|
||||
is($stdout,'t',"Check: temp_blks_read should not be 0.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT PGSM.temp_blks_written != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%FROM t1%\';', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: temp_blks_read should not be 0.");
|
||||
is($stdout,'t',"Check: temp_blks_written should not be 0.");
|
||||
|
||||
if ($PGSM::PG_MAJOR_VERSION >= 15)
|
||||
{
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.temp_blk_read_time) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%FROM t1%\';', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: temp_blk_read_time should not be 0.");
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.temp_blk_write_time) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%FROM t1%\'', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: temp_blk_write_time should not be 0.");
|
||||
}
|
||||
|
||||
# DROP EXTENSION
|
||||
$stdout = $node->safe_psql('postgres', 'DROP EXTENSION pg_stat_monitor;', extra_params => ['-a']);
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use File::Basename;
|
||||
use File::Compare;
|
||||
use File::Copy;
|
||||
use Text::Trim qw(trim);
|
||||
use Test::More;
|
||||
use lib 't';
|
||||
use pgsm;
|
||||
|
||||
# Get filename and create out file name and dirs where requried
|
||||
PGSM::setup_files_dir(basename($0));
|
||||
|
||||
if ($PGSM::PG_MAJOR_VERSION <= 16)
|
||||
{
|
||||
plan skip_all => "pg_stat_monitor test cases for versions 16 and below.";
|
||||
}
|
||||
|
||||
# Create new PostgreSQL node and do initdb
|
||||
my $node = PGSM->pgsm_init_pg();
|
||||
my $pgdata = $node->data_dir;
|
||||
|
||||
# Update postgresql.conf to include/load pg_stat_monitor library
|
||||
$node->append_conf('postgresql.conf', "shared_preload_libraries = 'pg_stat_monitor'");
|
||||
|
||||
# Set change postgresql.conf for this test case.
|
||||
$node->append_conf('postgresql.conf', "pg_stat_monitor.pgsm_bucket_time = 1");
|
||||
$node->append_conf('postgresql.conf', "pg_stat_monitor.pgsm_max_buckets = 3");
|
||||
$node->append_conf('postgresql.conf', "pg_stat_monitor.pgsm_normalized_query = yes");
|
||||
$node->append_conf('postgresql.conf', "pg_stat_monitor.pgsm_track = 'all'");
|
||||
|
||||
# Start server
|
||||
my $rt_value = $node->start;
|
||||
ok($rt_value == 1, "Start Server");
|
||||
|
||||
# Create EXTENSION and change out file permissions
|
||||
my ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'CREATE EXTENSION pg_stat_monitor;', extra_params => ['-a']);
|
||||
ok($cmdret == 0, "Create PGSM EXTENSION");
|
||||
PGSM::append_to_debug_file($stdout);
|
||||
|
||||
# Run 'SELECT pg_stat_monitor settings' and dump output to out file
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT name, setting, unit, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, pending_restart FROM pg_settings WHERE name LIKE '%pg_stat_monitor%';", extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
ok($cmdret == 0, "Print PGSM EXTENSION Settings");
|
||||
PGSM::append_to_debug_file($stdout);
|
||||
|
||||
# Run required commands/queries and dump output to out file.
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT pg_stat_monitor_reset();', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
ok($cmdret == 0, "Reset PGSM EXTENSION");
|
||||
PGSM::append_to_debug_file($stdout);
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT pg_sleep(1);', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
ok($cmdret == 0, "1 - Run pg_sleep(1)");
|
||||
PGSM::append_to_debug_file($stdout);
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT pg_sleep(1);', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
ok($cmdret == 0, "2 - Run pg_sleep(1)");
|
||||
PGSM::append_to_debug_file($stdout);
|
||||
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT pg_sleep(1);', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
ok($cmdret == 0, "3 - Run pg_sleep(1)");
|
||||
PGSM::append_to_debug_file($stdout);
|
||||
|
||||
# Check that we have more than one bucket
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT COUNT(bucket) != 0 AS PGSM FROM pg_stat_monitor WHERE query LIKE '%sleep%';", extra_params => ['-t', '-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: we have more that one bucket");
|
||||
|
||||
# Check that stats timestamps are different for each query/bucket
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT COUNT(DISTINCT stats_since) = COUNT(stats_since) AS PGSM FROM pg_stat_monitor WHERE query LIKE '%sleep%';", extra_params => ['-t', '-Pformat=unaligned','-Ptuples_only=on']);
|
||||
trim($stdout);
|
||||
is($stdout,'t',"Check: for every bucket stats_since should be unique");
|
||||
|
||||
# Check that minmax_stats_since always match stats_since
|
||||
($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT COUNT(*) AS ST FROM pg_stat_monitor WHERE query LIKE '%sleep%' AND stats_since != minmax_stats_since;", extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']);
|
||||
ok($stdout == 0, "Compare: Calls count is 1");
|
||||
PGSM::append_to_debug_file($stdout);
|
||||
|
||||
# DROP EXTENSION
|
||||
$stdout = $node->safe_psql('postgres', 'DROP EXTENSION pg_stat_monitor;', extra_params => ['-a']);
|
||||
ok($cmdret == 0, "DROP PGSM EXTENSION");
|
||||
PGSM::append_to_debug_file($stdout);
|
||||
|
||||
# Stop the server
|
||||
$node->stop;
|
||||
|
||||
# Done testing for this testcase file.
|
||||
done_testing();
|
|
@ -0,0 +1,151 @@
|
|||
CREATE EXTENSION pg_stat_monitor;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT name, setting, unit, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, pending_restart FROM pg_settings WHERE name='pg_stat_monitor.pgsm_query_shared_buffer';
|
||||
name | setting | unit | context | vartype | source | min_val | max_val | enumvals | boot_val | reset_val | pending_restart
|
||||
------------------------------------------+---------+------+------------+---------+--------------------+---------+---------+----------+----------+-----------+-----------------
|
||||
pg_stat_monitor.pgsm_query_shared_buffer | 1 | MB | postmaster | integer | configuration file | 1 | 10000 | | 20 | 1 | f
|
||||
(1 row)
|
||||
|
||||
CREATE database example;
|
||||
SELECT datname, substr(query,0,150) AS query, SUM(calls) AS calls FROM pg_stat_monitor GROUP BY datname, query ORDER BY datname, query, calls DESC Limit 20;
|
||||
datname | query | calls
|
||||
---------+-------------------------------------------------------------------------------------------------------------------------------------------------------+-------
|
||||
example | INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP) | 10000
|
||||
example | SELECT abalance FROM pgbench_accounts WHERE aid = $1 | 10000
|
||||
example | UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2 | 10000
|
||||
example | UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2 | 10000
|
||||
example | UPDATE pgbench_tellers SET tbalance = tbalance + $1 WHERE tid = $2 | 10000
|
||||
example | alter table pgbench_accounts add primary key (aid) | 1
|
||||
example | alter table pgbench_branches add primary key (bid) | 1
|
||||
example | alter table pgbench_tellers add primary key (tid) | 1
|
||||
example | begin | 10001
|
||||
example | commit | 10001
|
||||
example | copy pgbench_accounts from stdin with (freeze on) | 1
|
||||
example | copy pgbench_branches from stdin with (freeze on) | 1
|
||||
example | copy pgbench_tellers from stdin with (freeze on) | 1
|
||||
example | create table pgbench_accounts(aid int not null,bid int,abalance int,filler char(84)) with (fillfactor=100) | 1
|
||||
example | create table pgbench_branches(bid int not null,bbalance int,filler char(88)) with (fillfactor=100) | 1
|
||||
example | create table pgbench_history(tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)) | 1
|
||||
example | create table pgbench_tellers(tid int not null,bid int,tbalance int,filler char(84)) with (fillfactor=100) | 1
|
||||
example | drop table if exists pgbench_accounts, pgbench_branches, pgbench_history, pgbench_tellers | 1
|
||||
example | select count(*) from pgbench_branches | 1
|
||||
example | select o.n, p.partstrat, pg_catalog.count(i.inhparent) from pg_catalog.pg_class as c join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) cr | 1
|
||||
(20 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT name, setting, unit, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, pending_restart FROM pg_settings WHERE name='pg_stat_monitor.pgsm_query_shared_buffer';
|
||||
name | setting | unit | context | vartype | source | min_val | max_val | enumvals | boot_val | reset_val | pending_restart
|
||||
------------------------------------------+---------+------+------------+---------+--------------------+---------+---------+----------+----------+-----------+-----------------
|
||||
pg_stat_monitor.pgsm_query_shared_buffer | 2 | MB | postmaster | integer | configuration file | 1 | 10000 | | 20 | 2 | f
|
||||
(1 row)
|
||||
|
||||
SELECT datname, substr(query,0,150) AS query, SUM(calls) AS calls FROM pg_stat_monitor GROUP BY datname, query ORDER BY datname, query, calls DESC Limit 20;
|
||||
datname | query | calls
|
||||
---------+-------------------------------------------------------------------------------------------------------------------------------------------------------+-------
|
||||
example | INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP) | 10000
|
||||
example | SELECT abalance FROM pgbench_accounts WHERE aid = $1 | 10000
|
||||
example | UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2 | 10000
|
||||
example | UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2 | 10000
|
||||
example | UPDATE pgbench_tellers SET tbalance = tbalance + $1 WHERE tid = $2 | 10000
|
||||
example | alter table pgbench_accounts add primary key (aid) | 1
|
||||
example | alter table pgbench_branches add primary key (bid) | 1
|
||||
example | alter table pgbench_tellers add primary key (tid) | 1
|
||||
example | begin | 10001
|
||||
example | commit | 10001
|
||||
example | copy pgbench_accounts from stdin with (freeze on) | 1
|
||||
example | copy pgbench_branches from stdin with (freeze on) | 1
|
||||
example | copy pgbench_tellers from stdin with (freeze on) | 1
|
||||
example | create table pgbench_accounts(aid int not null,bid int,abalance int,filler char(84)) with (fillfactor=100) | 1
|
||||
example | create table pgbench_branches(bid int not null,bbalance int,filler char(88)) with (fillfactor=100) | 1
|
||||
example | create table pgbench_history(tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)) | 1
|
||||
example | create table pgbench_tellers(tid int not null,bid int,tbalance int,filler char(84)) with (fillfactor=100) | 1
|
||||
example | drop table if exists pgbench_accounts, pgbench_branches, pgbench_history, pgbench_tellers | 1
|
||||
example | select count(*) from pgbench_branches | 1
|
||||
example | select o.n, p.partstrat, pg_catalog.count(i.inhparent) from pg_catalog.pg_class as c join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) cr | 1
|
||||
(20 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT name, setting, unit, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, pending_restart FROM pg_settings WHERE name='pg_stat_monitor.pgsm_query_shared_buffer';
|
||||
name | setting | unit | context | vartype | source | min_val | max_val | enumvals | boot_val | reset_val | pending_restart
|
||||
------------------------------------------+---------+------+------------+---------+--------------------+---------+---------+----------+----------+-----------+-----------------
|
||||
pg_stat_monitor.pgsm_query_shared_buffer | 20 | MB | postmaster | integer | configuration file | 1 | 10000 | | 20 | 20 | f
|
||||
(1 row)
|
||||
|
||||
SELECT datname, substr(query,0,150) AS query, SUM(calls) AS calls FROM pg_stat_monitor GROUP BY datname, query ORDER BY datname, query, calls DESC Limit 20;
|
||||
datname | query | calls
|
||||
---------+-------------------------------------------------------------------------------------------------------------------------------------------------------+-------
|
||||
example | INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP) | 10000
|
||||
example | SELECT abalance FROM pgbench_accounts WHERE aid = $1 | 10000
|
||||
example | UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2 | 10000
|
||||
example | UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2 | 10000
|
||||
example | UPDATE pgbench_tellers SET tbalance = tbalance + $1 WHERE tid = $2 | 10000
|
||||
example | alter table pgbench_accounts add primary key (aid) | 1
|
||||
example | alter table pgbench_branches add primary key (bid) | 1
|
||||
example | alter table pgbench_tellers add primary key (tid) | 1
|
||||
example | begin | 10001
|
||||
example | commit | 10001
|
||||
example | copy pgbench_accounts from stdin with (freeze on) | 1
|
||||
example | copy pgbench_branches from stdin with (freeze on) | 1
|
||||
example | copy pgbench_tellers from stdin with (freeze on) | 1
|
||||
example | create table pgbench_accounts(aid int not null,bid int,abalance int,filler char(84)) with (fillfactor=100) | 1
|
||||
example | create table pgbench_branches(bid int not null,bbalance int,filler char(88)) with (fillfactor=100) | 1
|
||||
example | create table pgbench_history(tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)) | 1
|
||||
example | create table pgbench_tellers(tid int not null,bid int,tbalance int,filler char(84)) with (fillfactor=100) | 1
|
||||
example | drop table if exists pgbench_accounts, pgbench_branches, pgbench_history, pgbench_tellers | 1
|
||||
example | select count(*) from pgbench_branches | 1
|
||||
example | select o.n, p.partstrat, pg_catalog.count(i.inhparent) from pg_catalog.pg_class as c join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) cr | 1
|
||||
(20 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT name, setting, unit, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, pending_restart FROM pg_settings WHERE name='pg_stat_monitor.pgsm_query_shared_buffer';
|
||||
name | setting | unit | context | vartype | source | min_val | max_val | enumvals | boot_val | reset_val | pending_restart
|
||||
------------------------------------------+---------+------+------------+---------+--------------------+---------+---------+----------+----------+-----------+-----------------
|
||||
pg_stat_monitor.pgsm_query_shared_buffer | 2048 | MB | postmaster | integer | configuration file | 1 | 10000 | | 20 | 2048 | f
|
||||
(1 row)
|
||||
|
||||
SELECT datname, substr(query,0,150) AS query, SUM(calls) AS calls FROM pg_stat_monitor GROUP BY datname, query ORDER BY datname, query, calls DESC Limit 20;
|
||||
datname | query | calls
|
||||
---------+-------------------------------------------------------------------------------------------------------------------------------------------------------+-------
|
||||
example | INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP) | 10000
|
||||
example | SELECT abalance FROM pgbench_accounts WHERE aid = $1 | 10000
|
||||
example | UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2 | 10000
|
||||
example | UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2 | 10000
|
||||
example | UPDATE pgbench_tellers SET tbalance = tbalance + $1 WHERE tid = $2 | 10000
|
||||
example | alter table pgbench_accounts add primary key (aid) | 1
|
||||
example | alter table pgbench_branches add primary key (bid) | 1
|
||||
example | alter table pgbench_tellers add primary key (tid) | 1
|
||||
example | begin | 10001
|
||||
example | commit | 10001
|
||||
example | copy pgbench_accounts from stdin with (freeze on) | 1
|
||||
example | copy pgbench_branches from stdin with (freeze on) | 1
|
||||
example | copy pgbench_tellers from stdin with (freeze on) | 1
|
||||
example | create table pgbench_accounts(aid int not null,bid int,abalance int,filler char(84)) with (fillfactor=100) | 1
|
||||
example | create table pgbench_branches(bid int not null,bbalance int,filler char(88)) with (fillfactor=100) | 1
|
||||
example | create table pgbench_history(tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)) | 1
|
||||
example | create table pgbench_tellers(tid int not null,bid int,tbalance int,filler char(84)) with (fillfactor=100) | 1
|
||||
example | drop table if exists pgbench_accounts, pgbench_branches, pgbench_history, pgbench_tellers | 1
|
||||
example | select count(*) from pgbench_branches | 1
|
||||
example | select o.n, p.partstrat, pg_catalog.count(i.inhparent) from pg_catalog.pg_class as c join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) cr | 1
|
||||
(20 rows)
|
||||
|
||||
DROP EXTENSION pg_stat_monitor;
|
Loading…
Reference in New Issue