On Wed, Feb 26, 2014 at 5:45 AM, Alvaro Herrera <alvhe...@2ndquadrant.com> wrote: > Robert Haas escribió: >> On Mon, Feb 24, 2014 at 9:34 AM, Alvaro Herrera >> <alvhe...@2ndquadrant.com> wrote: >> > Yeah, erroring out seems good enough. Particularly if you add a hint >> > saying "please upgrade the extension". >> >> In past instances where this has come up, we have actually made the >> .so backward-compatible. See pg_stat_statements in particular. I'd >> prefer to keep to that precedent here. > > But pg_stat_statement is a user tool which is expected to have lots of > use, and backwards compatibility concerns because of people who might > have written tools on top of it. Not so with pageinspect. I don't > think we need to put in the same amount of effort. (Even though, > really, it's probably not all that difficult to support both cases. I > just don't see the point.) Actually a little bit of hacking I noticed that supporting both is as complicated as supporting only pg_lsn... Here is for example how I can get page_header to work across versions: - snprintf(lsnchar, sizeof(lsnchar), "%X/%X", - (uint32) (lsn >> 32), (uint32) lsn);
- values[0] = CStringGetTextDatum(lsnchar); + /* + * Do some version-related checks. pageinspect >= 1.2 uses pg_lsn + * instead of text when using this function for the LSN field. + */ + if (tupdesc->attrs[0]->atttypid == TEXTOID) + { + char lsnchar[64]; + snprintf(lsnchar, sizeof(lsnchar), "%X/%X", + (uint32) (lsn >> 32), (uint32) lsn); + values[0] = CStringGetTextDatum(lsnchar); + } + else + values[0] = LSNGetDatum(lsn); In this case an upgraded 9.4 server using pageinspect 1.1 or older simply goes through the text datatype path... You can find that in the patch attached. Regards, -- Michael
diff --git a/contrib/pageinspect/Makefile b/contrib/pageinspect/Makefile index 0e267eb..ee78cb2 100644 --- a/contrib/pageinspect/Makefile +++ b/contrib/pageinspect/Makefile @@ -4,8 +4,8 @@ MODULE_big = pageinspect OBJS = rawpage.o heapfuncs.o btreefuncs.o fsmfuncs.o EXTENSION = pageinspect -DATA = pageinspect--1.1.sql pageinspect--1.0--1.1.sql \ - pageinspect--unpackaged--1.0.sql +DATA = pageinspect--1.2.sql pageinspect--1.0--1.1.sql \ + pageinspect--1.1--1.2.sql pageinspect--unpackaged--1.0.sql ifdef USE_PGXS PG_CONFIG = pg_config diff --git a/contrib/pageinspect/pageinspect--1.1--1.2.sql b/contrib/pageinspect/pageinspect--1.1--1.2.sql new file mode 100644 index 0000000..5e23ca4 --- /dev/null +++ b/contrib/pageinspect/pageinspect--1.1--1.2.sql @@ -0,0 +1,18 @@ +/* contrib/pageinspect/pageinspect--1.1--1.2.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION pageinspect UPDATE TO 1.2" to load this file. \quit + +DROP FUNCTION page_header(bytea); +CREATE FUNCTION page_header(IN page bytea, + OUT lsn pg_lsn, + OUT checksum smallint, + OUT flags smallint, + OUT lower smallint, + OUT upper smallint, + OUT special smallint, + OUT pagesize smallint, + OUT version smallint, + OUT prune_xid xid) +AS 'MODULE_PATHNAME', 'page_header' +LANGUAGE C STRICT; diff --git a/contrib/pageinspect/pageinspect--1.1.sql b/contrib/pageinspect/pageinspect--1.1.sql deleted file mode 100644 index 22a47d5..0000000 --- a/contrib/pageinspect/pageinspect--1.1.sql +++ /dev/null @@ -1,107 +0,0 @@ -/* contrib/pageinspect/pageinspect--1.1.sql */ - --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "CREATE EXTENSION pageinspect" to load this file. \quit - --- --- get_raw_page() --- -CREATE FUNCTION get_raw_page(text, int4) -RETURNS bytea -AS 'MODULE_PATHNAME', 'get_raw_page' -LANGUAGE C STRICT; - -CREATE FUNCTION get_raw_page(text, text, int4) -RETURNS bytea -AS 'MODULE_PATHNAME', 'get_raw_page_fork' -LANGUAGE C STRICT; - --- --- page_header() --- -CREATE FUNCTION page_header(IN page bytea, - OUT lsn text, - OUT checksum smallint, - OUT flags smallint, - OUT lower smallint, - OUT upper smallint, - OUT special smallint, - OUT pagesize smallint, - OUT version smallint, - OUT prune_xid xid) -AS 'MODULE_PATHNAME', 'page_header' -LANGUAGE C STRICT; - --- --- heap_page_items() --- -CREATE FUNCTION heap_page_items(IN page bytea, - OUT lp smallint, - OUT lp_off smallint, - OUT lp_flags smallint, - OUT lp_len smallint, - OUT t_xmin xid, - OUT t_xmax xid, - OUT t_field3 int4, - OUT t_ctid tid, - OUT t_infomask2 integer, - OUT t_infomask integer, - OUT t_hoff smallint, - OUT t_bits text, - OUT t_oid oid) -RETURNS SETOF record -AS 'MODULE_PATHNAME', 'heap_page_items' -LANGUAGE C STRICT; - --- --- bt_metap() --- -CREATE FUNCTION bt_metap(IN relname text, - OUT magic int4, - OUT version int4, - OUT root int4, - OUT level int4, - OUT fastroot int4, - OUT fastlevel int4) -AS 'MODULE_PATHNAME', 'bt_metap' -LANGUAGE C STRICT; - --- --- bt_page_stats() --- -CREATE FUNCTION bt_page_stats(IN relname text, IN blkno int4, - OUT blkno int4, - OUT type "char", - OUT live_items int4, - OUT dead_items int4, - OUT avg_item_size int4, - OUT page_size int4, - OUT free_size int4, - OUT btpo_prev int4, - OUT btpo_next int4, - OUT btpo int4, - OUT btpo_flags int4) -AS 'MODULE_PATHNAME', 'bt_page_stats' -LANGUAGE C STRICT; - --- --- bt_page_items() --- -CREATE FUNCTION bt_page_items(IN relname text, IN blkno int4, - OUT itemoffset smallint, - OUT ctid tid, - OUT itemlen smallint, - OUT nulls bool, - OUT vars bool, - OUT data text) -RETURNS SETOF record -AS 'MODULE_PATHNAME', 'bt_page_items' -LANGUAGE C STRICT; - --- --- fsm_page_contents() --- -CREATE FUNCTION fsm_page_contents(IN page bytea) -RETURNS text -AS 'MODULE_PATHNAME', 'fsm_page_contents' -LANGUAGE C STRICT; diff --git a/contrib/pageinspect/pageinspect--1.2.sql b/contrib/pageinspect/pageinspect--1.2.sql new file mode 100644 index 0000000..15e8e1e --- /dev/null +++ b/contrib/pageinspect/pageinspect--1.2.sql @@ -0,0 +1,107 @@ +/* contrib/pageinspect/pageinspect--1.2.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION pageinspect" to load this file. \quit + +-- +-- get_raw_page() +-- +CREATE FUNCTION get_raw_page(text, int4) +RETURNS bytea +AS 'MODULE_PATHNAME', 'get_raw_page' +LANGUAGE C STRICT; + +CREATE FUNCTION get_raw_page(text, text, int4) +RETURNS bytea +AS 'MODULE_PATHNAME', 'get_raw_page_fork' +LANGUAGE C STRICT; + +-- +-- page_header() +-- +CREATE FUNCTION page_header(IN page bytea, + OUT lsn pg_lsn, + OUT checksum smallint, + OUT flags smallint, + OUT lower smallint, + OUT upper smallint, + OUT special smallint, + OUT pagesize smallint, + OUT version smallint, + OUT prune_xid xid) +AS 'MODULE_PATHNAME', 'page_header' +LANGUAGE C STRICT; + +-- +-- heap_page_items() +-- +CREATE FUNCTION heap_page_items(IN page bytea, + OUT lp smallint, + OUT lp_off smallint, + OUT lp_flags smallint, + OUT lp_len smallint, + OUT t_xmin xid, + OUT t_xmax xid, + OUT t_field3 int4, + OUT t_ctid tid, + OUT t_infomask2 integer, + OUT t_infomask integer, + OUT t_hoff smallint, + OUT t_bits text, + OUT t_oid oid) +RETURNS SETOF record +AS 'MODULE_PATHNAME', 'heap_page_items' +LANGUAGE C STRICT; + +-- +-- bt_metap() +-- +CREATE FUNCTION bt_metap(IN relname text, + OUT magic int4, + OUT version int4, + OUT root int4, + OUT level int4, + OUT fastroot int4, + OUT fastlevel int4) +AS 'MODULE_PATHNAME', 'bt_metap' +LANGUAGE C STRICT; + +-- +-- bt_page_stats() +-- +CREATE FUNCTION bt_page_stats(IN relname text, IN blkno int4, + OUT blkno int4, + OUT type "char", + OUT live_items int4, + OUT dead_items int4, + OUT avg_item_size int4, + OUT page_size int4, + OUT free_size int4, + OUT btpo_prev int4, + OUT btpo_next int4, + OUT btpo int4, + OUT btpo_flags int4) +AS 'MODULE_PATHNAME', 'bt_page_stats' +LANGUAGE C STRICT; + +-- +-- bt_page_items() +-- +CREATE FUNCTION bt_page_items(IN relname text, IN blkno int4, + OUT itemoffset smallint, + OUT ctid tid, + OUT itemlen smallint, + OUT nulls bool, + OUT vars bool, + OUT data text) +RETURNS SETOF record +AS 'MODULE_PATHNAME', 'bt_page_items' +LANGUAGE C STRICT; + +-- +-- fsm_page_contents() +-- +CREATE FUNCTION fsm_page_contents(IN page bytea) +RETURNS text +AS 'MODULE_PATHNAME', 'fsm_page_contents' +LANGUAGE C STRICT; diff --git a/contrib/pageinspect/pageinspect.control b/contrib/pageinspect/pageinspect.control index a412cf1..aecd91a 100644 --- a/contrib/pageinspect/pageinspect.control +++ b/contrib/pageinspect/pageinspect.control @@ -1,5 +1,5 @@ # pageinspect extension comment = 'inspect the contents of database pages at a low level' -default_version = '1.1' +default_version = '1.2' module_pathname = '$libdir/pageinspect' relocatable = true diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c index ff541ed..b153406 100644 --- a/contrib/pageinspect/rawpage.c +++ b/contrib/pageinspect/rawpage.c @@ -18,10 +18,12 @@ #include "access/htup_details.h" #include "catalog/catalog.h" #include "catalog/namespace.h" +#include "catalog/pg_type.h" #include "funcapi.h" #include "miscadmin.h" #include "storage/bufmgr.h" #include "utils/builtins.h" +#include "utils/pg_lsn.h" #include "utils/rel.h" PG_MODULE_MAGIC; @@ -180,7 +182,6 @@ page_header(PG_FUNCTION_ARGS) PageHeader page; XLogRecPtr lsn; - char lsnchar[64]; if (!superuser()) ereport(ERROR, @@ -207,10 +208,20 @@ page_header(PG_FUNCTION_ARGS) /* Extract information from the page header */ lsn = PageGetLSN(page); - snprintf(lsnchar, sizeof(lsnchar), "%X/%X", - (uint32) (lsn >> 32), (uint32) lsn); - values[0] = CStringGetTextDatum(lsnchar); + /* + * Do some version-related checks. pageinspect >= 1.2 uses pg_lsn + * instead of text when using this function for the LSN field. + */ + if (tupdesc->attrs[0]->atttypid == TEXTOID) + { + char lsnchar[64]; + snprintf(lsnchar, sizeof(lsnchar), "%X/%X", + (uint32) (lsn >> 32), (uint32) lsn); + values[0] = CStringGetTextDatum(lsnchar); + } + else + values[0] = LSNGetDatum(lsn); values[1] = UInt16GetDatum(page->pd_checksum); values[2] = UInt16GetDatum(page->pd_flags); values[3] = UInt16GetDatum(page->pd_lower);
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers