diff --git a/Makefile b/Makefile index dcdf17c..dfea104 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,9 @@ EXTENSION = pg_store_plans PG_VERSION := $(shell pg_config --version | sed "s/^PostgreSQL //" | sed "s/\.[0-9]*$$//") -DATA = pg_store_plans--1.9.sql +DATA = pg_store_plans--1.9.1.sql \ + pg_store_plans--1.9--1.9.1.sql \ + pg_store_plans--1.8--1.9.1.sql REGRESS = convert store REGRESS_OPTS = --temp-config=regress.conf diff --git a/pg_store_plans--1.8--1.9.1.sql b/pg_store_plans--1.8--1.9.1.sql new file mode 100644 index 0000000..3603b4a --- /dev/null +++ b/pg_store_plans--1.8--1.9.1.sql @@ -0,0 +1,94 @@ +/* pg_store_plans/pg_store_plans--1.8.0.3--1.9.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 + +/* Drop old versions */ +DROP VIEW pg_store_plans; +DROP FUNCTION pg_store_plans(); + +/* Now redefine */ +DO +$$ +BEGIN + IF (SELECT split_part(setting,'.',1) FROM pg_settings WHERE name = 'server_version')::int >= 17 THEN + CREATE FUNCTION pg_store_plans( + OUT userid oid, + OUT dbid oid, + OUT queryid int8, + OUT planid int8, + OUT plan text, + OUT calls int8, + OUT total_time float8, + OUT min_time float8, + OUT max_time float8, + OUT mean_time float8, + OUT stddev_time float8, + OUT rows int8, + OUT shared_blks_hit int8, + 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 first_call timestamptz, + OUT last_call timestamptz + ) + RETURNS SETOF record + AS 'MODULE_PATHNAME', 'pg_store_plans_1_9' + LANGUAGE C + VOLATILE PARALLEL SAFE; + ELSE + CREATE FUNCTION pg_store_plans( + OUT userid oid, + OUT dbid oid, + OUT queryid int8, + OUT planid int8, + OUT plan text, + OUT calls int8, + OUT total_time float8, + OUT min_time float8, + OUT max_time float8, + OUT mean_time float8, + OUT stddev_time float8, + OUT rows int8, + OUT shared_blks_hit int8, + 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 blk_read_time float8, + OUT blk_write_time float8, + OUT temp_blk_read_time float8, + OUT temp_blk_write_time float8, + OUT first_call timestamptz, + OUT last_call timestamptz + ) + RETURNS SETOF record + AS 'MODULE_PATHNAME', 'pg_store_plans_1_7' + LANGUAGE C + VOLATILE PARALLEL SAFE; + END IF; +END +$$ LANGUAGE plpgsql; + +-- Register a view on the function for ease of use. +CREATE VIEW pg_store_plans AS + SELECT * FROM pg_store_plans(); + +GRANT SELECT ON pg_store_plans TO PUBLIC; diff --git a/pg_store_plans--1.9--1.9.1.sql b/pg_store_plans--1.9--1.9.1.sql new file mode 100644 index 0000000..3603b4a --- /dev/null +++ b/pg_store_plans--1.9--1.9.1.sql @@ -0,0 +1,94 @@ +/* pg_store_plans/pg_store_plans--1.8.0.3--1.9.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 + +/* Drop old versions */ +DROP VIEW pg_store_plans; +DROP FUNCTION pg_store_plans(); + +/* Now redefine */ +DO +$$ +BEGIN + IF (SELECT split_part(setting,'.',1) FROM pg_settings WHERE name = 'server_version')::int >= 17 THEN + CREATE FUNCTION pg_store_plans( + OUT userid oid, + OUT dbid oid, + OUT queryid int8, + OUT planid int8, + OUT plan text, + OUT calls int8, + OUT total_time float8, + OUT min_time float8, + OUT max_time float8, + OUT mean_time float8, + OUT stddev_time float8, + OUT rows int8, + OUT shared_blks_hit int8, + 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 first_call timestamptz, + OUT last_call timestamptz + ) + RETURNS SETOF record + AS 'MODULE_PATHNAME', 'pg_store_plans_1_9' + LANGUAGE C + VOLATILE PARALLEL SAFE; + ELSE + CREATE FUNCTION pg_store_plans( + OUT userid oid, + OUT dbid oid, + OUT queryid int8, + OUT planid int8, + OUT plan text, + OUT calls int8, + OUT total_time float8, + OUT min_time float8, + OUT max_time float8, + OUT mean_time float8, + OUT stddev_time float8, + OUT rows int8, + OUT shared_blks_hit int8, + 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 blk_read_time float8, + OUT blk_write_time float8, + OUT temp_blk_read_time float8, + OUT temp_blk_write_time float8, + OUT first_call timestamptz, + OUT last_call timestamptz + ) + RETURNS SETOF record + AS 'MODULE_PATHNAME', 'pg_store_plans_1_7' + LANGUAGE C + VOLATILE PARALLEL SAFE; + END IF; +END +$$ LANGUAGE plpgsql; + +-- Register a view on the function for ease of use. +CREATE VIEW pg_store_plans AS + SELECT * FROM pg_store_plans(); + +GRANT SELECT ON pg_store_plans TO PUBLIC; diff --git a/pg_store_plans--1.9.1.sql b/pg_store_plans--1.9.1.sql new file mode 100644 index 0000000..42a9d26 --- /dev/null +++ b/pg_store_plans--1.9.1.sql @@ -0,0 +1,146 @@ +/* pg_store_plans/pg_store_plans--1.9.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 pg_store_plans_info +CREATE FUNCTION pg_store_plans_info( + OUT dealloc bigint, + OUT stats_reset timestamp with time zone +) +RETURNS record +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT VOLATILE PARALLEL SAFE; + +CREATE VIEW pg_store_plans_info AS + SELECT * FROM pg_store_plans_info(); + +GRANT SELECT ON pg_store_plans_info TO PUBLIC; + +-- Register functions. +CREATE FUNCTION pg_store_plans_reset() +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C PARALLEL SAFE; +CREATE FUNCTION pg_store_plans_shorten(text) +RETURNS text +AS 'MODULE_PATHNAME' +LANGUAGE C +RETURNS NULL ON NULL INPUT PARALLEL SAFE; +CREATE FUNCTION pg_store_plans_normalize(text) +RETURNS text +AS 'MODULE_PATHNAME' +LANGUAGE C +RETURNS NULL ON NULL INPUT PARALLEL SAFE; +CREATE FUNCTION pg_store_plans_jsonplan(text) +RETURNS text +AS 'MODULE_PATHNAME' +LANGUAGE C +RETURNS NULL ON NULL INPUT PARALLEL SAFE; +CREATE FUNCTION pg_store_plans_textplan(text) +RETURNS text +AS 'MODULE_PATHNAME' +LANGUAGE C +RETURNS NULL ON NULL INPUT PARALLEL SAFE; +CREATE FUNCTION pg_store_plans_yamlplan(text) +RETURNS text +AS 'MODULE_PATHNAME' +LANGUAGE C +RETURNS NULL ON NULL INPUT PARALLEL SAFE; +CREATE FUNCTION pg_store_plans_xmlplan(text) +RETURNS text +AS 'MODULE_PATHNAME' +LANGUAGE C +RETURNS NULL ON NULL INPUT PARALLEL SAFE; +CREATE FUNCTION pg_store_plans_hash_query(text) +RETURNS oid +AS 'MODULE_PATHNAME' +LANGUAGE C +RETURNS NULL ON NULL INPUT PARALLEL SAFE; +DO +$$ +BEGIN + IF (SELECT split_part(setting,'.',1) FROM pg_settings WHERE name = 'server_version')::int >= 17 THEN + CREATE FUNCTION pg_store_plans( + OUT userid oid, + OUT dbid oid, + OUT queryid int8, + OUT planid int8, + OUT plan text, + OUT calls int8, + OUT total_time float8, + OUT min_time float8, + OUT max_time float8, + OUT mean_time float8, + OUT stddev_time float8, + OUT rows int8, + OUT shared_blks_hit int8, + 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 first_call timestamptz, + OUT last_call timestamptz + ) + RETURNS SETOF record + AS 'MODULE_PATHNAME', 'pg_store_plans_1_9' + LANGUAGE C + VOLATILE PARALLEL SAFE; + ELSE + CREATE FUNCTION pg_store_plans( + OUT userid oid, + OUT dbid oid, + OUT queryid int8, + OUT planid int8, + OUT plan text, + OUT calls int8, + OUT total_time float8, + OUT min_time float8, + OUT max_time float8, + OUT mean_time float8, + OUT stddev_time float8, + OUT rows int8, + OUT shared_blks_hit int8, + 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 blk_read_time float8, + OUT blk_write_time float8, + OUT temp_blk_read_time float8, + OUT temp_blk_write_time float8, + OUT first_call timestamptz, + OUT last_call timestamptz + ) + RETURNS SETOF record + AS 'MODULE_PATHNAME', 'pg_store_plans_1_7' + LANGUAGE C + VOLATILE PARALLEL SAFE; + END IF; +END +$$ LANGUAGE plpgsql; + +-- Register a view on the function for ease of use. +CREATE VIEW pg_store_plans AS + SELECT * FROM pg_store_plans(); + +GRANT SELECT ON pg_store_plans TO PUBLIC; + +-- Don't want this to be available to non-superusers. +REVOKE ALL ON FUNCTION pg_store_plans_reset() FROM PUBLIC; diff --git a/pg_store_plans--1.9.sql b/pg_store_plans--1.9.sql deleted file mode 100644 index 9f2bec3..0000000 --- a/pg_store_plans--1.9.sql +++ /dev/null @@ -1,104 +0,0 @@ -/* pg_store_plans/pg_store_plans--1.9.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 pg_store_plans_info -CREATE FUNCTION pg_store_plans_info( - OUT dealloc bigint, - OUT stats_reset timestamp with time zone -) -RETURNS record -AS 'MODULE_PATHNAME' -LANGUAGE C STRICT VOLATILE PARALLEL SAFE; - -CREATE VIEW pg_store_plans_info AS - SELECT * FROM pg_store_plans_info(); - -GRANT SELECT ON pg_store_plans_info TO PUBLIC; - --- Register functions. -CREATE FUNCTION pg_store_plans_reset() -RETURNS void -AS 'MODULE_PATHNAME' -LANGUAGE C PARALLEL SAFE; -CREATE FUNCTION pg_store_plans_shorten(text) -RETURNS text -AS 'MODULE_PATHNAME' -LANGUAGE C -RETURNS NULL ON NULL INPUT PARALLEL SAFE; -CREATE FUNCTION pg_store_plans_normalize(text) -RETURNS text -AS 'MODULE_PATHNAME' -LANGUAGE C -RETURNS NULL ON NULL INPUT PARALLEL SAFE; -CREATE FUNCTION pg_store_plans_jsonplan(text) -RETURNS text -AS 'MODULE_PATHNAME' -LANGUAGE C -RETURNS NULL ON NULL INPUT PARALLEL SAFE; -CREATE FUNCTION pg_store_plans_textplan(text) -RETURNS text -AS 'MODULE_PATHNAME' -LANGUAGE C -RETURNS NULL ON NULL INPUT PARALLEL SAFE; -CREATE FUNCTION pg_store_plans_yamlplan(text) -RETURNS text -AS 'MODULE_PATHNAME' -LANGUAGE C -RETURNS NULL ON NULL INPUT PARALLEL SAFE; -CREATE FUNCTION pg_store_plans_xmlplan(text) -RETURNS text -AS 'MODULE_PATHNAME' -LANGUAGE C -RETURNS NULL ON NULL INPUT PARALLEL SAFE; -CREATE FUNCTION pg_store_plans_hash_query(text) -RETURNS oid -AS 'MODULE_PATHNAME' -LANGUAGE C -RETURNS NULL ON NULL INPUT PARALLEL SAFE; -CREATE FUNCTION pg_store_plans( - OUT userid oid, - OUT dbid oid, - OUT queryid int8, - OUT planid int8, - OUT plan text, - OUT calls int8, - OUT total_time float8, - OUT min_time float8, - OUT max_time float8, - OUT mean_time float8, - OUT stddev_time float8, - OUT rows int8, - OUT shared_blks_hit int8, - 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 first_call timestamptz, - OUT last_call timestamptz -) -RETURNS SETOF record -AS 'MODULE_PATHNAME', 'pg_store_plans_1_9' -LANGUAGE C -VOLATILE PARALLEL SAFE; - --- Register a view on the function for ease of use. -CREATE VIEW pg_store_plans AS - SELECT * FROM pg_store_plans(); - -GRANT SELECT ON pg_store_plans TO PUBLIC; - --- Don't want this to be available to non-superusers. -REVOKE ALL ON FUNCTION pg_store_plans_reset() FROM PUBLIC; diff --git a/pg_store_plans.c b/pg_store_plans.c index 3b2e64b..680400d 100644 --- a/pg_store_plans.c +++ b/pg_store_plans.c @@ -423,7 +423,7 @@ _PG_init(void) "Sets the maximum number of plans tracked by pg_store_plans.", NULL, &store_size, - 1000, + 5000, 100, INT_MAX, PGC_POSTMASTER, @@ -485,7 +485,7 @@ _PG_init(void) "Minimum duration to record plan in milliseconds.", NULL, &min_duration, - 0, + 10, 0, INT_MAX, PGC_SUSET, @@ -531,7 +531,7 @@ _PG_init(void) "Log timings.", NULL, &log_timing, - true, + false, PGC_SUSET, 0, NULL, @@ -752,6 +752,15 @@ pgsp_shmem_startup(void) pgver != PGSP_PG_MAJOR_VERSION) goto data_error; + /* check if num is out of range */ + if (num < 0 || num > store_size) + { + ereport(LOG, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Invalid number of entries in file: %d", num))); + goto data_error; + } + for (i = 0; i < num; i++) { pgspEntry temp; @@ -944,6 +953,10 @@ pgsp_shmem_shutdown(int code, Datum arg) /* Unlink query-texts file; it's not needed while shutdown */ unlink(PGSP_TEXT_FILE); + if (pbuffer){ + free(pbuffer); // or free(pbuffer) + pbuffer = NULL; + } return; error: @@ -954,6 +967,10 @@ pgsp_shmem_shutdown(int code, Datum arg) if (file) FreeFile(file); unlink(PGSP_DUMP_FILE ".tmp"); + if (pbuffer){ + free(pbuffer); // or free(pbuffer) + pbuffer = NULL; + } } @@ -1234,6 +1251,7 @@ pgsp_store(char *plan, queryid_t queryId, return; /* Set up key for hashtable search */ + memset(&key, 0, sizeof(key)); key.userid = GetUserId(); key.dbid = MyDatabaseId; key.queryid = queryId; @@ -1612,6 +1630,9 @@ pg_store_plans_internal(FunctionCallInfo fcinfo, else pstr = SHMEM_PLAN_PTR(entry); + if (pstr == NULL) + continue; /* Ignore any entries with bogus texts */ + switch (plan_format) { case PLAN_FORMAT_TEXT: @@ -1691,21 +1712,38 @@ pg_store_plans_internal(FunctionCallInfo fcinfo, values[i++] = Int64GetDatumFast(tmp.local_blks_written); values[i++] = Int64GetDatumFast(tmp.temp_blks_read); values[i++] = Int64GetDatumFast(tmp.temp_blks_written); - values[i++] = Float8GetDatumFast(tmp.shared_blk_read_time); - values[i++] = Float8GetDatumFast(tmp.shared_blk_write_time); if (api_version >= PGSP_V1_9) { #if PG_VERSION_NUM >= 170000 + values[i++] = Float8GetDatumFast(tmp.shared_blk_read_time); + values[i++] = Float8GetDatumFast(tmp.shared_blk_write_time); values[i++] = Float8GetDatumFast(tmp.local_blk_read_time); values[i++] = Float8GetDatumFast(tmp.local_blk_write_time); #else values[i++] = Float8GetDatumFast(0.0); values[i++] = Float8GetDatumFast(0.0); + values[i++] = Float8GetDatumFast(tmp.blk_read_time); + values[i++] = Float8GetDatumFast(tmp.blk_write_time); #endif } if (api_version >= PGSP_V1_7) { +#if PG_VERSION_NUM >= 170000 + if (api_version < PGSP_V1_9) + { + values[i++] = Float8GetDatumFast(tmp.shared_blk_read_time+ + tmp.local_blk_read_time); + values[i++] = Float8GetDatumFast(tmp.shared_blk_write_time+ + tmp.local_blk_write_time); + } +#else + if (api_version < PGSP_V1_9) + { + values[i++] = Float8GetDatumFast(tmp.blk_read_time); + values[i++] = Float8GetDatumFast(tmp.blk_write_time); + } +#endif values[i++] = Float8GetDatumFast(tmp.temp_blk_read_time); values[i++] = Float8GetDatumFast(tmp.temp_blk_write_time); } @@ -1723,6 +1761,11 @@ pg_store_plans_internal(FunctionCallInfo fcinfo, } LWLockRelease(shared_state->lock); + + if (pbuffer){ + free(pbuffer); // or free(pbuffer) + pbuffer = NULL; + } } /* Number of output arguments (columns) for pg_stat_statements_info */ diff --git a/pg_store_plans.control b/pg_store_plans.control index 74cb304..7b0aa51 100644 --- a/pg_store_plans.control +++ b/pg_store_plans.control @@ -1,5 +1,5 @@ # pg_store_plans extension comment = 'track plan statistics of all SQL statements executed' -default_version = '1.9' +default_version = '1.9.1' module_pathname = '$libdir/pg_store_plans' relocatable = true