diff options
author | Tom Lane | 2009-06-08 16:22:44 +0000 |
---|---|---|
committer | Tom Lane | 2009-06-08 16:22:44 +0000 |
commit | 896d5ca8038b866c14b28b0edaf6e15b35052da4 (patch) | |
tree | c8644f263d58237baba51f59f248e9ae6effcd57 | |
parent | 8378846fdffb329d33cb8b3732f56c5d9c92efc0 (diff) |
Fix contrib/pageinspect to not create an ABI breakage between 8.3 and 8.4.
The original implementation of the 3-argument form of get_raw_page() risked
core dumps if the 8.3 SQL function definition was mistakenly used with the
8.4 module, which is entirely likely after a dump-and-reload upgrade. To
protect 8.4 beta testers against upgrade problems, add a check on PG_NARGS.
In passing, fix missed additions to the uninstall script, and polish the
docs a trifle.
-rw-r--r-- | contrib/pageinspect/pageinspect.sql.in | 8 | ||||
-rw-r--r-- | contrib/pageinspect/rawpage.c | 56 | ||||
-rw-r--r-- | contrib/pageinspect/uninstall_pageinspect.sql | 2 | ||||
-rw-r--r-- | doc/src/sgml/pageinspect.sgml | 10 |
4 files changed, 63 insertions, 13 deletions
diff --git a/contrib/pageinspect/pageinspect.sql.in b/contrib/pageinspect/pageinspect.sql.in index e320bec7e2..ca6406a6d3 100644 --- a/contrib/pageinspect/pageinspect.sql.in +++ b/contrib/pageinspect/pageinspect.sql.in @@ -6,15 +6,15 @@ SET search_path = public; -- -- get_raw_page() -- -CREATE OR REPLACE FUNCTION get_raw_page(text, text, int4) +CREATE OR REPLACE FUNCTION get_raw_page(text, int4) RETURNS bytea AS 'MODULE_PATHNAME', 'get_raw_page' LANGUAGE C STRICT; -CREATE OR REPLACE FUNCTION get_raw_page(text, int4) +CREATE OR REPLACE FUNCTION get_raw_page(text, text, int4) RETURNS bytea -AS $$ SELECT get_raw_page($1, 'main', $2); $$ -LANGUAGE SQL STRICT; +AS 'MODULE_PATHNAME', 'get_raw_page_fork' +LANGUAGE C STRICT; -- -- page_header() diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c index 08d61fab87..55ef637836 100644 --- a/contrib/pageinspect/rawpage.c +++ b/contrib/pageinspect/rawpage.c @@ -29,8 +29,13 @@ PG_MODULE_MAGIC; Datum get_raw_page(PG_FUNCTION_ARGS); +Datum get_raw_page_fork(PG_FUNCTION_ARGS); Datum page_header(PG_FUNCTION_ARGS); +static bytea *get_raw_page_internal(text *relname, ForkNumber forknum, + BlockNumber blkno); + + /* * get_raw_page * @@ -42,13 +47,56 @@ Datum get_raw_page(PG_FUNCTION_ARGS) { text *relname = PG_GETARG_TEXT_P(0); + uint32 blkno = PG_GETARG_UINT32(1); + bytea *raw_page; + + /* + * We don't normally bother to check the number of arguments to a C + * function, but here it's needed for safety because early 8.4 beta + * releases mistakenly redefined get_raw_page() as taking three arguments. + */ + if (PG_NARGS() != 2) + ereport(ERROR, + (errmsg("wrong number of arguments to get_raw_page()"), + errhint("Run the updated pageinspect.sql script."))); + + raw_page = get_raw_page_internal(relname, MAIN_FORKNUM, blkno); + + PG_RETURN_BYTEA_P(raw_page); +} + +/* + * get_raw_page_fork + * + * Same, for any fork + */ +PG_FUNCTION_INFO_V1(get_raw_page_fork); + +Datum +get_raw_page_fork(PG_FUNCTION_ARGS) +{ + text *relname = PG_GETARG_TEXT_P(0); text *forkname = PG_GETARG_TEXT_P(1); uint32 blkno = PG_GETARG_UINT32(2); + bytea *raw_page; ForkNumber forknum; - Relation rel; - RangeVar *relrv; + forknum = forkname_to_number(text_to_cstring(forkname)); + + raw_page = get_raw_page_internal(relname, forknum, blkno); + + PG_RETURN_BYTEA_P(raw_page); +} + +/* + * workhorse + */ +static bytea * +get_raw_page_internal(text *relname, ForkNumber forknum, BlockNumber blkno) +{ bytea *raw_page; + RangeVar *relrv; + Relation rel; char *raw_page_data; Buffer buf; @@ -57,8 +105,6 @@ get_raw_page(PG_FUNCTION_ARGS) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to use raw functions")))); - forknum = forkname_to_number(text_to_cstring(forkname)); - relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); rel = relation_openrv(relrv, AccessShareLock); @@ -105,7 +151,7 @@ get_raw_page(PG_FUNCTION_ARGS) relation_close(rel, AccessShareLock); - PG_RETURN_BYTEA_P(raw_page); + return raw_page; } /* diff --git a/contrib/pageinspect/uninstall_pageinspect.sql b/contrib/pageinspect/uninstall_pageinspect.sql index f92b20ebe6..362c60449e 100644 --- a/contrib/pageinspect/uninstall_pageinspect.sql +++ b/contrib/pageinspect/uninstall_pageinspect.sql @@ -4,8 +4,10 @@ SET search_path = public; DROP FUNCTION get_raw_page(text, int4); +DROP FUNCTION get_raw_page(text, text, int4); DROP FUNCTION page_header(bytea); DROP FUNCTION heap_page_items(bytea); DROP FUNCTION bt_metap(text); DROP FUNCTION bt_page_stats(text, int4); DROP FUNCTION bt_page_items(text, int4); +DROP FUNCTION fsm_page_contents(bytea); diff --git a/doc/src/sgml/pageinspect.sgml b/doc/src/sgml/pageinspect.sgml index 8f4094439f..87028091c8 100644 --- a/doc/src/sgml/pageinspect.sgml +++ b/doc/src/sgml/pageinspect.sgml @@ -27,8 +27,9 @@ <function>get_raw_page</function> reads the specified block of the named table and returns a copy as a <type>bytea</> value. This allows a single time-consistent copy of the block to be obtained. - <literal>fork</literal> should be <literal>'main'</literal> for the main - data fork, or <literal>'fsm'</literal> for the FSM. + <replaceable>fork</replaceable> should be <literal>'main'</literal> for + the main data fork, or <literal>'fsm'</literal> for the free space map, + or <literal>'vm'</literal> for the visibility map. </para> </listitem> </varlistentry> @@ -40,8 +41,9 @@ <listitem> <para> - A shorthand of above, for reading from the main fork. Equal to - <literal>get_raw_page(relname, 0, blkno)</literal> + A shorthand version of <function>get_raw_page</function>, for reading + from the main fork. Equivalent to + <literal>get_raw_page(relname, 'main', blkno)</literal> </para> </listitem> </varlistentry> |