- Successfully builds on PG14, and also passes PG13 regression tests.
- The new node types added in PG14 are not yet supported.
Co-Author: Julien Rouhaud <julien.rouhaud@free.fr>
# pg_stat_plan/Makefile
MODULES = pg_store_plans
-STOREPLANSVER = 1.5
+STOREPLANSVER = 1.6
MODULE_big = pg_store_plans
OBJS = pg_store_plans.o pgsp_json.o pgsp_json_text.o pgsp_explain.o
PG_VERSION := $(shell pg_config --version | sed "s/^PostgreSQL //" | sed "s/\.[0-9]*$$//")
-DATA = pg_store_plans--1.5.sql
+DATA = pg_store_plans--1.6.sql
REGRESS = convert store
REGRESS_OPTS = --temp-config=regress.conf
include $(top_srcdir)/contrib/contrib-global.mk
endif
-STARBALL13 = pg_store_plans13-$(STOREPLANSVER).tar.gz
-STARBALLS = $(STARBALL13)
+STARBALL14 = pg_store_plans14-$(STOREPLANSVER).tar.gz
+STARBALLS = $(STARBALL14)
TARSOURCES = Makefile *.c *.h \
pg_store_plans--*.sql \
## These entries need running server
DBNAME = postgres
-rpms: rpm13
+rpms: rpm14
$(STARBALLS): $(TARSOURCES)
if [ -h $(subst .tar.gz,,$@) ]; then rm $(subst .tar.gz,,$@); fi
tar -chzf $@ $(addprefix $(subst .tar.gz,,$@)/, $^)
rm $(subst .tar.gz,,$@)
-rpm13: $(STARBALL13)
- MAKE_ROOT=`pwd` rpmbuild -bb SPECS/pg_store_plans13.spec
+rpm14: $(STARBALL14)
+ MAKE_ROOT=`pwd` rpmbuild -bb SPECS/pg_store_plans14.spec
testfiles: convert.out convert.sql
# SPEC file for pg_store_plans
# Copyright(c) 2021, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
-%define _pgdir /usr/pgsql-13
+%define _pgdir /usr/pgsql-14
%define _bindir %{_pgdir}/bin
%define _libdir %{_pgdir}/lib
%define _datadir %{_pgdir}/share
%endif
## Set general information for pg_store_plans.
-Summary: Record executed plans on PostgreSQL 13
-Name: pg_store_plans13
-Version: 1.5
+Summary: Record executed plans on PostgreSQL 14
+Name: pg_store_plans14
+Version: 1.6
Release: 1%{?dist}
License: BSD
Group: Applications/Databases
Vendor: NIPPON TELEGRAPH AND TELEPHONE CORPORATION
## We use postgresql-devel package
-BuildRequires: postgresql13-devel
-Requires: postgresql13-libs
+BuildRequires: postgresql14-devel
+Requires: postgresql14-libs
## Description for "pg_store_plans"
%description
pg_store_plans provides capability to record statistics for every plan
executed on PostgreSQL.
-Note that this package is available for only PostgreSQL 13.
+Note that this package is available for only PostgreSQL 14.
%package llvmjit
-Requires: postgresql13-server, postgresql13-llvmjit
-Requires: pg_store_plans13 = 1.5
-Summary: Just-in-time compilation support for pg_store_plans13
+Requires: postgresql14-server, postgresql14-llvmjit
+Requires: pg_store_plans14 = 1.6
+Summary: Just-in-time compilation support for pg_store_plans14
%description llvmjit
-Just-in-time compilation support for pg_store_plans13
+Just-in-time compilation support for pg_store_plans14
## pre work for build pg_store_plans
%prep
-PATH=/usr/pgsql-13/bin:$PATH
+PATH=/usr/pgsql-14/bin:$PATH
if [ "${MAKE_ROOT}" != "" ]; then
pushd ${MAKE_ROOT}
make clean %{name}-%{version}.tar.gz
## Set variables for build environment
%build
-PATH=/usr/pgsql-13/bin:$PATH
+PATH=/usr/pgsql-14/bin:$PATH
pg_config
make USE_PGXS=1 %{?_smp_mflags}
## Set variables for install
%install
rm -rf %{buildroot}
-PATH=/usr/pgsql-13/bin:$PATH
+PATH=/usr/pgsql-14/bin:$PATH
make install DESTDIR=%{buildroot}
%clean
%defattr(0755,root,root)
%{_libdir}/pg_store_plans.so
%defattr(0644,root,root)
-%{_datadir}/extension/pg_store_plans--1.5.sql
+%{_datadir}/extension/pg_store_plans--1.6.sql
%{_datadir}/extension/pg_store_plans.control
%files llvmjit
# History of pg_store_plans.
%changelog
+* Wed Nov xx 2021 Tatsuro Yamada, Julien Rouhaud, Kyotaro Horiguchi
+- Version 1.6. Supports PostgreSQL 14
* Wed Jan 27 2021 Kyotaro Horiguchi
- Version 1.5. Supports PostgreSQL 13
* Thu Jan 30 2020 Kyotaro Horiguchi
--- /dev/null
+SET client_min_messages = 'error';
+CREATE EXTENSION IF NOT EXISTS pg_store_plans;
+CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
+SELECT pg_stat_statements_reset();
+ pg_stat_statements_reset
+--------------------------
+
+(1 row)
+
+SELECT pg_store_plans_reset();
+ pg_store_plans_reset
+----------------------
+
+(1 row)
+
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a int);
+CREATE INDEX ON t1 (a);
+INSERT INTO t1 (SELECT a FROM generate_series(0, 9999) a);
+RESET enable_seqscan;
+RESET enable_bitmapscan;
+SELECT count(*) FROM (SELECT * FROM t1) AS x;
+ count
+-------
+ 10000
+(1 row)
+
+SET enable_seqscan TO false;
+SELECT count(*) FROM (SELECT * FROM t1) AS x;
+ count
+-------
+ 10000
+(1 row)
+
+SELECT count(*) FROM (SELECT * FROM t1) AS x;
+ count
+-------
+ 10000
+(1 row)
+
+SET enable_bitmapscan TO false;
+SELECT count(*) FROM (SELECT * FROM t1) AS x;
+ count
+-------
+ 10000
+(1 row)
+
+SELECT count(*) FROM (SELECT * FROM t1) AS x;
+ count
+-------
+ 10000
+(1 row)
+
+SELECT count(*) FROM (SELECT * FROM t1) AS x;
+ count
+-------
+ 10000
+(1 row)
+
+RESET enable_seqscan;
+RESET enable_bitmapscan;
+CREATE OR REPLACE FUNCTION test_explain() RETURNS text AS
+$x$
+DECLARE
+ r record;
+ s text;
+ p text;
+ totalrows int;
+ totalcalls int;
+ first bool;
+BEGIN
+ s := '';
+ first = true;
+ SELECT calls, rows INTO totalcalls, totalrows
+ FROM pg_stat_statements
+ WHERE query = 'SELECT count(*) FROM (SELECT * FROM t1) AS x';
+
+ FOR r IN SELECT s.query as q, p.plan as p, p.calls as c, p.rows r
+ FROM pg_stat_statements s
+ JOIN pg_store_plans p ON (s.queryid = p.queryid_stat_statements)
+ WHERE s.query = 'SELECT count(*) FROM (SELECT * FROM t1) AS x'
+ ORDER BY p.calls
+ LOOP
+ IF first then
+ s = r.q || E'\n totalcalls=' || totalcalls ||
+ ' , totalrows=' || totalrows || E'\n';
+ first := false;
+ END IF;
+ p := regexp_replace(r.p, '=[0-9.]+([^0-9.])', '=xxx\1', 'g');
+ s := s || p || E'\n calls=' || r.c || ', rows=' || r.r || E'\n';
+ END LOOP;
+
+ RETURN s;
+END
+$x$
+LANGUAGE plpgsql;
+SELECT test_explain();
+ test_explain
+-----------------------------------------------------------------------------
+ SELECT count(*) FROM (SELECT * FROM t1) AS x +
+ totalcalls=6 , totalrows=6 +
+ Aggregate (cost=xxx rows=xxx width=xxx) +
+ Async Capable: false +
+ -> Seq Scan on t1 (cost=xxx rows=xxx width=xxx) +
+ Async Capable: false +
+ calls=1, rows=1 +
+ Aggregate (cost=xxx rows=xxx width=xxx) +
+ Async Capable: false +
+ -> Bitmap Heap Scan on t1 (cost=xxx rows=xxx width=xxx) +
+ Async Capable: false +
+ -> Bitmap Index Scan using t1_a_idx (cost=xxx rows=xxx width=xxx)+
+ Async Capable: false +
+ calls=2, rows=2 +
+ Aggregate (cost=xxx rows=xxx width=xxx) +
+ Async Capable: false +
+ -> Index Only Scan using t1_a_idx on t1 (cost=xxx rows=xxx width=xxx) +
+ Async Capable: false +
+ calls=3, rows=3 +
+
+(1 row)
+
+DROP FUNCTION test_explain();
+DROP TABLE t1;
-/* pg_store_plans/pg_store_plans--1.4.sql */
+/* pg_store_plans/pg_store_plans--1.6.sql */
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION pg_store_plans" to load this file. \quit
#define COMPTAG_TYPE QueryCompletion
#endif
+#if PG_VERSION_NUM < 140000
+#define ROLE_PG_READ_ALL_STATS DEFAULT_ROLE_READ_ALL_STATS
+#endif
+
static void pgsp_shmem_startup(void);
static void pgsp_shmem_shutdown(int code, Datum arg);
static void pgsp_ExecutorStart(QueryDesc *queryDesc, int eflags);
static void pgsp_ExecutorFinish(QueryDesc *queryDesc);
static void pgsp_ExecutorEnd(QueryDesc *queryDesc);
static void pgsp_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
+#if PG_VERSION_NUM >= 140000
+ bool readOnlyTree,
+#endif
ProcessUtilityContext context, ParamListInfo params,
QueryEnvironment *queryEnv,
DestReceiver *dest, COMPTAG_TYPE *completionTag);
MemoryContext oldcxt;
oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt);
- queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL);
+ queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL
+#if PG_VERSION_NUM >= 140000
+ , false
+#endif
+ );
MemoryContextSwitchTo(oldcxt);
}
*/
static void
pgsp_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
+#if PG_VERSION_NUM >= 140000
+ bool readOnlyTree,
+#endif
ProcessUtilityContext context, ParamListInfo params,
QueryEnvironment *queryEnv,
DestReceiver *dest, COMPTAG_TYPE *completionTag)
{
if (prev_ProcessUtility)
prev_ProcessUtility(pstmt, queryString,
+#if PG_VERSION_NUM >= 140000
+ readOnlyTree,
+#endif
context, params, queryEnv,
dest, completionTag);
else
standard_ProcessUtility(pstmt, queryString,
+#if PG_VERSION_NUM >= 140000
+ readOnlyTree,
+#endif
context, params, queryEnv,
dest, completionTag);
}
MemoryContext per_query_ctx;
MemoryContext oldcontext;
Oid userid = GetUserId();
- bool is_allowed_role = is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS);
+ bool is_allowed_role = is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS);
HASH_SEQ_STATUS hash_seq;
StatEntry *entry;
# pg_store_plans extension
comment = 'track plan statistics of all SQL statements executed'
-default_version = '1.5'
+default_version = '1.6'
module_pathname = '$libdir/pg_store_plans'
relocatable = true
{
ResultRelInfo *rInfo;
bool show_relname;
- int numrels = queryDesc->estate->es_num_result_relations;
+#if PG_VERSION_NUM < 140000
+ int numrels = queryDesc->estate->es_num_result_relations;
+ int nr;
+#else
+ List *resultrels;
+ List *routerels;
+#endif
List *targrels = queryDesc->estate->es_trig_target_relations;
- int nr;
ListCell *l;
+
+#if PG_VERSION_NUM >= 140000
+ resultrels = queryDesc->estate->es_opened_result_relations;
+ routerels = queryDesc->estate->es_tuple_routing_result_relations;
+ targrels = queryDesc->estate->es_trig_target_relations;
+#endif
pgspExplainOpenGroup("Triggers", "Triggers", false, es);
-
+
+#if PG_VERSION_NUM < 140000
show_relname = (numrels > 1 || targrels != NIL);
rInfo = queryDesc->estate->es_result_relations;
for (nr = 0; nr < numrels; rInfo++, nr++)
+#else
+ show_relname = (list_length(resultrels) > 1 ||
+ routerels != NIL || targrels != NIL);
+ foreach(l, resultrels)
+ {
+ rInfo = (ResultRelInfo *) lfirst(l);
+#endif
report_triggers(rInfo, show_relname, es);
-
+#if PG_VERSION_NUM >= 140000
+ }
+
+ foreach(l, routerels)
+ {
+ rInfo = (ResultRelInfo *) lfirst(l);
+ report_triggers(rInfo, show_relname, es);
+ }
+#endif
+
foreach(l, targrels)
{
rInfo = (ResultRelInfo *) lfirst(l);