Fix contrib/pageinspect to not create an ABI breakage between 8.3 and 8.4.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 Jun 2009 16:22:44 +0000 (16:22 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 Jun 2009 16:22:44 +0000 (16:22 +0000)
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.

contrib/pageinspect/pageinspect.sql.in
contrib/pageinspect/rawpage.c
contrib/pageinspect/uninstall_pageinspect.sql
doc/src/sgml/pageinspect.sgml

index e320bec7e2e110fc5a63b9915e95ec3b422387d6..ca6406a6d3e937a663cdb54ee6a96eb47dcb65ba 100644 (file)
@@ -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()
index 08d61fab879d017a1d66663e81ddaa7fb9bc3e9f..55ef63783685e9040d300002a53cdde747772e87 100644 (file)
 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
  *
@@ -40,15 +45,58 @@ PG_FUNCTION_INFO_V1(get_raw_page);
 
 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;
 }
 
 /*
index f92b20ebe65062b9b35a4cbcd1b783f8a4a609eb..362c60449e13e38ac7ccae3348862bf8ff989001 100644 (file)
@@ -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);
index 8f4094439fba23113fd55820dd969b55351c886c..87028091c8fadc455975c3e28cd4641b7f0a81bc 100644 (file)
@@ -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>