8 Commits

Author SHA1 Message Date
e3b9612db0 Update copyright date. 2014-06-10 13:24:38 -04:00
093effb3f8 Add .gitignore. 2014-06-10 13:10:11 -04:00
bbd992bc26 Preliminary updates for Postgres 9.3. 2013-06-06 18:33:16 +00:00
4f71071d5b Updates for latest Postgres 9.2 sources.
We no longer need pg_crc.c, and hence not a source tree, yay.
2012-03-12 16:08:33 +00:00
883c674f6f Preliminary support for SP-GiST indexes. 2011-12-18 00:11:29 +00:00
3551cfe252 Update for Postgres 9.1; add knowledge of some more flag bits;
improve Makefile to be able to build a release tarball.
2011-11-26 22:14:08 +00:00
2c9c61c841 Fix odd printout of hasnulls/hasvarwidths flags for index tuples.
Per a gripe some months ago from Alvaro.
2011-01-18 02:36:38 +00:00
ac96dfbaca Assorted adjustments to prepare pg_filedump for its new life.
Add PostgreSQL Global Development Group to the copyright notices, and
remove a couple of no-longer-appropriate references to Red Hat.
Unfortunately I can't undo Red Hat's choice of GPL licensing, but it is
what it is.

Also reduce the pain of version-stamping by coalescing references to the
version into one pair of macros, and removing not-especially-useful
change logs.  IMO the commit logs serve that purpose just as well.
2011-01-18 02:28:26 +00:00
7 changed files with 327 additions and 343 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/pg_filedump.o
/pg_filedump

174
ChangeLog
View File

@ -1,174 +0,0 @@
2010-12-29 Tom Lane <tgl@redhat.com>
* pg_filedump.c, .h: Update version and copyright date for
PostgreSQL 9.0 (there aren't any on-disk layout changes in 9.0).
2009-07-08 Tom Lane <tgl@redhat.com>
* pg_filedump.c: Update for changes in pg_control contents in
PostgreSQL 8.4.
* pg_filedump.c, .h: Update version and copyright date.
2008-02-08 Tom Lane <tgl@redhat.com>
* pg_filedump.c: Updates for various representation changes in
PostgreSQL 8.3; in particular there is finally a trustworthy way
to tell apart the various types of index special space.
* pg_filedump.c, .h: Update version and copyright date.
2007-02-14 Tom Lane <tgl@redhat.com>
* pg_filedump.c, .h: Remove rtree support (gone in PostgreSQL 8.2)
and add GIN support. Other updates for changes in index special
section contents in 8.2.
* pg_filedump.c: Repair old bug that misreported header length by
4 bytes.
* pg_filedump.c, .h: Update version and copyright date.
2005-11-21 Tom Lane <tgl@redhat.com>
* pg_filedump.c, .h: Adjust to support PostgreSQL 8.1 tuple format
and control file layout.
* pg_filedump.c, .h: Update version and copyright date.
* Makefile.contrib: Update for PGXS changes.
2005-02-10 Tom Lane <tgl@redhat.com>
* pg_filedump.c, .h: Adjust to support PostgreSQL 8.0 tuple format.
* pg_filedump.c, .h: Update version and copyright date.
2003-09-29 Patrick Macdonald <patrickm@redhat.com>
* pg_filedump.c (GetSpecialSectionType): Distinguish between btree and
hash index pages using the hasho_filler field.
(FormatHeader): Verify index page header is btree before dumping meta
data.
(FormatSpecial): Format index areas based on precalculated special
section type.
* pg_filedump.h: Add distinct index special section types.
2003-05-30 Patrick Macdonald <patrickm@redhat.com>
* pg_filedump.c: Bumped version up to 3.0.
2003-04-17 Patrick Macdonald <patrickm@redhat.com>
* pg_filedump.c (DisplayOptions): Update version and copyright
date.
(FormatHeader): Display btree meta data as part of the header
if this is a btree meta page.
(FormatItem): Remove older version defines.
(FormatSpecial): Add new btree defines.
(FormatControl): Remove older version defines.
* pg_filedump.h: Update version and copyright date, remove older
version structure defines.
2003-04-17 Patrick Macdonald <patrickm@redhat.com>
* pg_filedump.c: Updated header, copyright and indentation.
* pg_filedump.h: ditto.
2002-12-18 Patrick Macdonald <patrickm@redhat.com>
* pg_filedump.c: Version 1.1 of the tool, moved
declarations to proper header,
(GetBlockSize): Cache block size locally,
(CreateDumpFileHeader): Increment the release minor,
(FormatHeader): Add block version number to output,
(FormatItem): Support new heap tuple layout,
(FormatControl): Support additional entries in the
control file.
* pg_filedump.h: New file.
* README.pg_filedump: Updated for version control.
2002-10-16 Patrick Macdonald <patrickm@redhat.com>
* rhdb-utils.build: Updated branch level.
2002-09-24 Andrew Overholt <overholt@redhat.com>
* rhdb-utils.build: Change cvsroot to reflect new server.
2002-09-11 Andrew Overholt <overholt@redhat.com>
* rhdb-utils.spec: Change release number to 1.
2002-07-29 Liam Stewart <liams@redhat.com>
* rhdb-utils.build: Tightened the cvs module so checkouts don't
take forever.
(get_cvs): Checkout instead of export.
(build): Call build_srpm to build SRPM.
2002-07-10 Liam Stewart <liams@redhat.com>
* rhdb-utils.build (build): Use rpmbuild instead of rpm; ignore
dependencies.
2002-07-08 Liam Stewart <liams@redhat.com>
* rhdb-utils.spec: Updated summary and description text. Bumped
release.
2002-07-04 Liam Stewart <liams@redhat.com>
* rhdb-utils.build: $download -> $downloaddir
* rhdb-utils.spec: New file.
* rhdb-utils.build: New file.
* rpm-extras/pg_filedump-crc.patch: New file.
* rpm-extras/pg_filedump-make.patch: New file.
2002-03-08 Patrick Macdonald <patrickm@redhat.com>
* pg_filedump.c (FormatItem): Remove EXTENDED,
add XMAX_COMMITED and XMAX_INVALID, add proper
t_bits[] processing, fix typo.
* Makefile.contrib: New file.
2002-03-04 Patrick Macdonald <patrickm@redhat.com>
* README.pg_filedump: sources merge.
2002-02-04 Patrick Macdonald <patrickm@redhat.com>
* pg_filedump.c: Add macro to set options and
flag duplicates, move copyright out of the
header block, use MAXALIGN when determining
special section size
* README.pg_filedump: New file.
2002-02-01 Patrick Macdonald <patrickm@redhat.com>
* pg_filedump.c: Alter copyright info to GPL.
* pg_filedump.c: Minor tweaks to printf() formatting,
(FormatItem): Add new parameter to receive the
formatting method.
(FormatItemBlock): Determine and pass the format
method to FormatItem().
2002-01-30 Patrick Macdonald <patrickm@redhat.com>
* pg_filedump.c: Added -B to valid control file
dump options.
* Makefile: Add -Wmissing-prototypes and
-Wmissing-declarations.
2002-01-29 Patrick Macdonald <patrickm@redhat.com>
* pg_filedump.c: Renamed from pgfiledump.c
2002-01-29 Patrick Macdonald <patrickm@redhat.com>
* pgfiledump.c: Scrubbed the code, added support
for CRC checking, improved readability, fixed
unsigned vs signed problems.
* Makefile: Added pg_crc.c to support CRC checks.
2002-01-28 Patrick Macdonald <patrickm@redhat.com>
* pgfiledump.c: Added FormatControl() to support
dumping of the PostgreSQL control file.
2002-01-25 Patrick Macdonald <patrickm@redhat.com>
* Makefile, pgfiledump.c: New file.

View File

@ -1,26 +1,34 @@
# View README.pg_filedump first # View README.pg_filedump first
# note this must match version macros in pg_filedump.h
FD_VERSION=9.3.0
CC=gcc CC=gcc
CFLAGS=-g -O -Wall -Wmissing-prototypes -Wmissing-declarations CFLAGS=-g -O -Wall -Wmissing-prototypes -Wmissing-declarations
INCLUDE=/usr/include/pgsql/server # If working with a PG source directory, point PGSQL_INCLUDE_DIR to its
# src/include subdirectory. If working with an installed tree, point to
# the server include subdirectory, eg /usr/local/include/postgresql/server
PGSQL_INCLUDE_DIR=../../pgsql/src/include
# PGSQL MUST POINT TO pgsql SOURCE DIRECTORY
PGSQL=../../../../postgres/pgsql
CRC_SRC=${PGSQL}/src/backend/utils/hash DISTFILES= README.pg_filedump Makefile Makefile.contrib \
CRC_INCLUDE=${PGSQL}/src pg_filedump.h pg_filedump.c
all: pg_filedump all: pg_filedump
pg_filedump: pg_filedump.o pg_crc.o pg_filedump: pg_filedump.o
${CC} ${CFLAGS} -o pg_filedump pg_filedump.o pg_crc.o ${CC} ${CFLAGS} -o pg_filedump pg_filedump.o
pg_filedump.o: pg_filedump.c pg_filedump.o: pg_filedump.c
${CC} ${CFLAGS} -I${INCLUDE} pg_filedump.c -c ${CC} ${CFLAGS} -I${PGSQL_INCLUDE_DIR} pg_filedump.c -c
pg_crc.o: ${CRC_SRC}/pg_crc.c dist:
${CC} ${CFLAGS} -I${CRC_INCLUDE} -I${INCLUDE} ${CRC_SRC}/pg_crc.c -c rm -rf pg_filedump-${FD_VERSION} pg_filedump-${FD_VERSION}.tar.gz
mkdir pg_filedump-${FD_VERSION}
cp -p ${DISTFILES} pg_filedump-${FD_VERSION}
tar cfz pg_filedump-${FD_VERSION}.tar.gz pg_filedump-${FD_VERSION}
rm -rf pg_filedump-${FD_VERSION}
clean: clean:
rm -rf *.o pg_filedump rm -f *.o pg_filedump

View File

@ -1,7 +1,5 @@
PROGRAM = pg_filedump PROGRAM = pg_filedump
OBJS = pg_filedump.o pg_crc.o OBJS = pg_filedump.o
EXTRA_CLEAN = pg_crc.c
DOCS = README.pg_filedump DOCS = README.pg_filedump
@ -15,6 +13,3 @@ top_builddir = ../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk include $(top_srcdir)/contrib/contrib-global.mk
endif endif
pg_crc.c: $(top_srcdir)/src/backend/utils/hash/pg_crc.c
rm -f $@ && $(LN_S) $< .

View File

@ -1,19 +1,20 @@
pg_filedump - Display formatted contents of a PostgreSQL heap/index/control pg_filedump - Display formatted contents of a PostgreSQL heap, index,
file. or control file.
Copyright (c) 2002-2010 Red Hat, Inc. Copyright (c) 2002-2010 Red Hat, Inc.
Copyright (c) 2011-2014, PostgreSQL Global Development Group
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
Author: Patrick Macdonald <patrickm@redhat.com> Original Author: Patrick Macdonald <patrickm@redhat.com>
Version: 9.0.0
Overview:
------------------------------------------------------------------------ ------------------------------------------------------------------------
Overview:
pg_filedump is a utility to format PostgreSQL heap/index/control files pg_filedump is a utility to format PostgreSQL heap/index/control files
into a human-readable form. You can format/dump the files several ways, into a human-readable form. You can format/dump the files several ways,
as listed in the Invocation section, as well as dumping straight binary. as listed in the Invocation section, as well as dumping straight binary.
@ -22,63 +23,42 @@ The type of file (heap/index) can usually be determined automatically
by the content of the blocks within the file. However, to format a by the content of the blocks within the file. However, to format a
pg_control file you must use the -c option. pg_control file you must use the -c option.
The default is to format the entire file using the block size listed on The default is to format the entire file using the block size listed in
block 0 (heap/index files) and display block relative addresses. These block 0 and display block relative addresses. These defaults can be
defaults can be modified using run-time options. modified using run-time options.
Some options may seem strange but they're there for a reason. For Some options may seem strange but they're there for a reason. For
example, block size. It's there because if the header of block 0 is example, block size. It's there because if the header of block 0 is
corrupt, you need a method of forcing a block size. corrupt, you need a method of forcing a block size.
Release Notes / Databases Supported
-----------------------------------------------------------------------
V9.0.0 Must be compiled against a PostgreSQL 9.0 installation.
Supports: PostgreSQL 9.0.x
V8.4.0 Must be compiled against a PostgreSQL 8.4 installation.
Supports: PostgreSQL 8.4.x
V8.3.0 Must be compiled against a PostgreSQL 8.3 installation.
Supports: PostgreSQL 8.3.x
V8.2.0 Must be compiled against a PostgreSQL 8.2 installation.
Supports: PostgreSQL 8.2.x
V8.1.1 Must be compiled against a PostgreSQL 8.1 installation.
Supports: PostgreSQL 8.1.x
V4.0 Must be compiled against a PostgreSQL 8.0 installation.
Supports: PostgreSQL 8.0.x
V3.0 Must be compiled against a PostgreSQL 7.4 installation.
Supports: PostgreSQL 7.4.x
V2.0 Must be compiled against a PostgreSQL 7.3 installation.
Supports: PostgreSQL - Red Hat Edition 3.0,
Red Hat Database 2.x, Red Hat Database 1.x
PostgreSQL 7.3.x, PostgreSQL 7.2.x, PostgreSQL 7.1.x
V1.0 Must be compiled against a PostgreSQL 7.1 or PostgreSQL 7.2
installation.
Supports: Red Hat Database 2.x, Red Hat Database 1.x
PostgreSQL 7.2.x, PostgreSQL 7.1.x
Compile/Installation:
------------------------------------------------------------------------ ------------------------------------------------------------------------
There are two makefiles included in this package. Makefile is a Compile/Installation:
standalone makefile for pg_filedump. Alter the include and src
variables to point to the proper directories. Makefile.contrib can be To compile pg_filedump, you will need to have a properly configured
used if the package was untarred in the contrib directory of a PostgreSQL source tree or complete install tree (with include files)
PostgreSQL build tree. of the appropriate PostgreSQL major version.
There are two makefiles included in this package. Makefile is a standalone
makefile for pg_filedump. Alter its PGSQL_INCLUDE_DIR variable to point to
the PostgreSQL include files. Makefile.contrib can be used if this package
was untarred in the contrib directory of a PostgreSQL build tree.
make make
make install (if in the contrib directory) make install (if using Makefile.contrib)
It is also possible to use Makefile.contrib without being in the contrib
directory:
make -f Makefile.contrib USE_PGXS=1
This method requires that the pg_config program be in your PATH, but should
not require any manual adjustments of the Makefile.
Invocation:
------------------------------------------------------------------------ ------------------------------------------------------------------------
Invocation:
pg_filedump [-abcdfhixy] [-R startblock [endblock]] [-S blocksize] file pg_filedump [-abcdfhixy] [-R startblock [endblock]] [-S blocksize] file
Defaults are: relative addressing, range of the entire file, block size Defaults are: relative addressing, range of the entire file, block size
@ -107,3 +87,6 @@ The following options are valid for control files:
-c Interpret the file listed as a control file -c Interpret the file listed as a control file
-f Display formatted content dump along with interpretation -f Display formatted content dump along with interpretation
-S Force block size to [blocksize] -S Force block size to [blocksize]
In most cases it's recommended to use the -i and -f options to get
the most useful dump output.

View File

@ -1,9 +1,9 @@
/* /*
* pg_filedump.c - PostgreSQL file dump utility for dumping and * pg_filedump.c - PostgreSQL file dump utility for dumping and
* formatting heap (data), index and control files. * formatting heap (data), index and control files.
* Version 9.0.0 for PostgreSQL 9.0
* *
* Copyright (c) 2002-2010 Red Hat, Inc. All rights reserved. * Copyright (c) 2002-2010 Red Hat, Inc.
* Copyright (c) 2011-2014, PostgreSQL Global Development Group
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,14 +19,13 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* Author: Patrick Macdonald <patrickm@redhat.com> * Original Author: Patrick Macdonald <patrickm@redhat.com>
*
* Component of: PostgreSQL - Red Hat Edition - Utilities / Tools
*
*/ */
#include "pg_filedump.h" #include "pg_filedump.h"
#include "utils/pg_crc_tables.h"
// Global variables for ease of use mostly // Global variables for ease of use mostly
static FILE *fp = NULL; // File to dump or format static FILE *fp = NULL; // File to dump or format
static char *fileName = NULL; // File name for display static char *fileName = NULL; // File name for display
@ -63,12 +62,15 @@ DisplayOptions (unsigned int validOptions)
{ {
if (validOptions == OPT_RC_COPYRIGHT) if (validOptions == OPT_RC_COPYRIGHT)
printf printf
("\nVersion 9.0.0 (PostgreSQL 9.0) Copyright (c) 2002-2010 Red Hat, Inc.\n"); ("\nVersion %s (for %s)"
"\nCopyright (c) 2002-2010 Red Hat, Inc."
"\nCopyright (c) 2011-2014, PostgreSQL Global Development Group\n",
FD_VERSION, FD_PG_VERSION);
printf printf
("\nUsage: pg_filedump [-abcdfhixy] [-R startblock [endblock]] [-S blocksize] file\n\n" ("\nUsage: pg_filedump [-abcdfhixy] [-R startblock [endblock]] [-S blocksize] file\n\n"
"Display formatted contents of a PostgreSQL heap/index/control file\n" "Display formatted contents of a PostgreSQL heap/index/control file\n"
" Defaults are: relative addressing, range of the entire file, block\n" "Defaults are: relative addressing, range of the entire file, block\n"
" size as listed on block 0 in the file\n\n" " size as listed on block 0 in the file\n\n"
"The following options are valid for heap and index files:\n" "The following options are valid for heap and index files:\n"
" -a Display absolute addresses when formatting (Block header\n" " -a Display absolute addresses when formatting (Block header\n"
@ -91,7 +93,7 @@ DisplayOptions (unsigned int validOptions)
" -c Interpret the file listed as a control file\n" " -c Interpret the file listed as a control file\n"
" -f Display formatted content dump along with interpretation\n" " -f Display formatted content dump along with interpretation\n"
" -S Force block size to [blocksize]\n" " -S Force block size to [blocksize]\n"
"\nReport bugs to <rhdb@sources.redhat.com>\n"); "\nReport bugs to <pgsql-bugs@postgresql.org>\n");
} }
// Iterate through the provided options and set the option flags. // Iterate through the provided options and set the option flags.
@ -286,7 +288,7 @@ ConsumeOptions (int numOptions, char **options)
SET_OPTION (itemOptions, ITEM_DETAIL, 'i'); SET_OPTION (itemOptions, ITEM_DETAIL, 'i');
break; break;
// Interpret items as index values // Interpret items as standard index values
case 'x': case 'x':
SET_OPTION (itemOptions, ITEM_INDEX, 'x'); SET_OPTION (itemOptions, ITEM_INDEX, 'x');
if (itemOptions & ITEM_HEAP) if (itemOptions & ITEM_HEAP)
@ -434,20 +436,29 @@ GetSpecialSectionType (Page page)
rc = SPEC_SECT_ERROR_BOUNDARY; rc = SPEC_SECT_ERROR_BOUNDARY;
else else
{ {
// we may need to examine last 2 bytes of page to identify index
uint16 *ptype = (uint16 *) (buffer + blockSize - sizeof(uint16));
specialSize = blockSize - specialOffset; specialSize = blockSize - specialOffset;
// If there is a special section, use its size to guess its // If there is a special section, use its size to guess its
// contents // contents, checking the last 2 bytes of the page in cases
// that are ambiguous. Note we don't attempt to dereference
// the pointers without checking bytesToFormat == blockSize.
if (specialSize == 0) if (specialSize == 0)
rc = SPEC_SECT_NONE; rc = SPEC_SECT_NONE;
else if (specialSize == MAXALIGN (sizeof (uint32))) else if (specialSize == MAXALIGN (sizeof (uint32)))
{ {
// If MAXALIGN is 8, this could be either a sequence or GIN // If MAXALIGN is 8, this could be either a sequence or
// SP-GiST or GIN.
if (bytesToFormat == blockSize) if (bytesToFormat == blockSize)
{ {
specialValue = *((int *) (buffer + specialOffset)); specialValue = *((int *) (buffer + specialOffset));
if (specialValue == SEQUENCE_MAGIC) if (specialValue == SEQUENCE_MAGIC)
rc = SPEC_SECT_SEQUENCE; rc = SPEC_SECT_SEQUENCE;
else if (specialSize == MAXALIGN (sizeof (SpGistPageOpaqueData)) &&
*ptype == SPGIST_PAGE_ID)
rc = SPEC_SECT_INDEX_SPGIST;
else if (specialSize == MAXALIGN (sizeof (GinPageOpaqueData))) else if (specialSize == MAXALIGN (sizeof (GinPageOpaqueData)))
rc = SPEC_SECT_INDEX_GIN; rc = SPEC_SECT_INDEX_GIN;
else else
@ -456,6 +467,12 @@ GetSpecialSectionType (Page page)
else else
rc = SPEC_SECT_ERROR_UNKNOWN; rc = SPEC_SECT_ERROR_UNKNOWN;
} }
// SP-GiST and GIN have same size special section, so check
// the page ID bytes first.
else if (specialSize == MAXALIGN (sizeof (SpGistPageOpaqueData)) &&
bytesToFormat == blockSize &&
*ptype == SPGIST_PAGE_ID)
rc = SPEC_SECT_INDEX_SPGIST;
else if (specialSize == MAXALIGN (sizeof (GinPageOpaqueData))) else if (specialSize == MAXALIGN (sizeof (GinPageOpaqueData)))
rc = SPEC_SECT_INDEX_GIN; rc = SPEC_SECT_INDEX_GIN;
else if (specialSize > 2 && bytesToFormat == blockSize) else if (specialSize > 2 && bytesToFormat == blockSize)
@ -463,15 +480,13 @@ GetSpecialSectionType (Page page)
// As of 8.3, BTree, Hash, and GIST all have the same size // As of 8.3, BTree, Hash, and GIST all have the same size
// special section, but the last two bytes of the section // special section, but the last two bytes of the section
// can be checked to determine what's what. // can be checked to determine what's what.
uint16 ptype = *(uint16 *) (buffer + blockSize - sizeof(uint16)); if (*ptype <= MAX_BT_CYCLE_ID &&
if (ptype <= MAX_BT_CYCLE_ID &&
specialSize == MAXALIGN (sizeof (BTPageOpaqueData))) specialSize == MAXALIGN (sizeof (BTPageOpaqueData)))
rc = SPEC_SECT_INDEX_BTREE; rc = SPEC_SECT_INDEX_BTREE;
else if (ptype == HASHO_PAGE_ID && else if (*ptype == HASHO_PAGE_ID &&
specialSize == MAXALIGN (sizeof (HashPageOpaqueData))) specialSize == MAXALIGN (sizeof (HashPageOpaqueData)))
rc = SPEC_SECT_INDEX_HASH; rc = SPEC_SECT_INDEX_HASH;
else if (ptype == GIST_PAGE_ID && else if (*ptype == GIST_PAGE_ID &&
specialSize == MAXALIGN (sizeof (GISTPageOpaqueData))) specialSize == MAXALIGN (sizeof (GISTPageOpaqueData)))
rc = SPEC_SECT_INDEX_GIST; rc = SPEC_SECT_INDEX_GIST;
else else
@ -528,12 +543,13 @@ CreateDumpFileHeader (int numOptions, char **options)
printf printf
("\n*******************************************************************\n" ("\n*******************************************************************\n"
"* PostgreSQL File/Block Formatted Dump Utility - Version 9.0.0\n*\n" "* PostgreSQL File/Block Formatted Dump Utility - Version %s\n"
"*\n"
"* File: %s\n" "* File: %s\n"
"* Options used: %s\n*\n" "* Options used: %s\n*\n"
"* Dump created on: %s" "* Dump created on: %s"
"*******************************************************************\n", "*******************************************************************\n",
fileName, (strlen (optionBuffer)) ? optionBuffer : "None", FD_VERSION, fileName, (strlen (optionBuffer)) ? optionBuffer : "None",
ctime (&rightNow)); ctime (&rightNow));
} }
@ -582,6 +598,8 @@ FormatHeader (Page page)
strcat (flagString, "HAS_FREE_LINES|"); strcat (flagString, "HAS_FREE_LINES|");
if (pageHeader->pd_flags & PD_PAGE_FULL) if (pageHeader->pd_flags & PD_PAGE_FULL)
strcat (flagString, "PAGE_FULL|"); strcat (flagString, "PAGE_FULL|");
if (pageHeader->pd_flags & PD_ALL_VISIBLE)
strcat (flagString, "ALL_VISIBLE|");
if (strlen (flagString)) if (strlen (flagString))
flagString[strlen (flagString) - 1] = '\0'; flagString[strlen (flagString) - 1] = '\0';
@ -591,15 +609,15 @@ FormatHeader (Page page)
" Block: Size %4d Version %4u Upper %4u (0x%04hx)\n" " Block: Size %4d Version %4u Upper %4u (0x%04hx)\n"
" LSN: logid %6d recoff 0x%08x Special %4u (0x%04hx)\n" " LSN: logid %6d recoff 0x%08x Special %4u (0x%04hx)\n"
" Items: %4d Free Space: %4u\n" " Items: %4d Free Space: %4u\n"
" TLI: 0x%04x Prune XID: 0x%08x Flags: 0x%04x (%s)\n" " Checksum: 0x%04x Prune XID: 0x%08x Flags: 0x%04x (%s)\n"
" Length (including item array): %u\n\n", " Length (including item array): %u\n\n",
pageOffset, pageHeader->pd_lower, pageHeader->pd_lower, pageOffset, pageHeader->pd_lower, pageHeader->pd_lower,
(int) PageGetPageSize (page), blockVersion, (int) PageGetPageSize (page), blockVersion,
pageHeader->pd_upper, pageHeader->pd_upper, pageHeader->pd_upper, pageHeader->pd_upper,
pageLSN.xlogid, pageLSN.xrecoff, (uint32) (pageLSN >> 32), (uint32) pageLSN,
pageHeader->pd_special, pageHeader->pd_special, pageHeader->pd_special, pageHeader->pd_special,
maxOffset, pageHeader->pd_upper - pageHeader->pd_lower, maxOffset, pageHeader->pd_upper - pageHeader->pd_lower,
pageHeader->pd_tli, pageHeader->pd_prune_xid, pageHeader->pd_checksum, pageHeader->pd_prune_xid,
pageHeader->pd_flags, flagString, pageHeader->pd_flags, flagString,
headerBytes); headerBytes);
@ -684,10 +702,30 @@ FormatItemBlock (Page page)
formatAs = ITEM_INDEX; formatAs = ITEM_INDEX;
else if (itemOptions & ITEM_HEAP) else if (itemOptions & ITEM_HEAP)
formatAs = ITEM_HEAP; formatAs = ITEM_HEAP;
else if (specialType != SPEC_SECT_NONE)
formatAs = ITEM_INDEX;
else else
switch (specialType)
{
case SPEC_SECT_INDEX_BTREE:
case SPEC_SECT_INDEX_HASH:
case SPEC_SECT_INDEX_GIST:
case SPEC_SECT_INDEX_GIN:
formatAs = ITEM_INDEX;
break;
case SPEC_SECT_INDEX_SPGIST:
{
SpGistPageOpaque spgpo =
(SpGistPageOpaque) ((char *) page +
((PageHeader) page)->pd_special);
if (spgpo->flags & SPGIST_LEAF)
formatAs = ITEM_SPG_LEAF;
else
formatAs = ITEM_SPG_INNER;
}
break;
default:
formatAs = ITEM_HEAP; formatAs = ITEM_HEAP;
break;
}
for (x = 1; x < (maxOffset + 1); x++) for (x = 1; x < (maxOffset + 1); x++)
{ {
@ -751,9 +789,16 @@ static void
FormatItem (unsigned int numBytes, unsigned int startIndex, FormatItem (unsigned int numBytes, unsigned int startIndex,
unsigned int formatAs) unsigned int formatAs)
{ {
// It is an index item, so dump the index header static const char * const spgist_tupstates[4] = {
"LIVE",
"REDIRECT",
"DEAD",
"PLACEHOLDER"
};
if (formatAs == ITEM_INDEX) if (formatAs == ITEM_INDEX)
{ {
// It is an IndexTuple item, so dump the index header
if (numBytes < SizeOfIptrData) if (numBytes < SizeOfIptrData)
{ {
if (numBytes) if (numBytes)
@ -766,17 +811,96 @@ FormatItem (unsigned int numBytes, unsigned int startIndex,
" Has Nulls: %u Has Varwidths: %u\n\n", " Has Nulls: %u Has Varwidths: %u\n\n",
((uint32) ((itup->t_tid.ip_blkid.bi_hi << 16) | ((uint32) ((itup->t_tid.ip_blkid.bi_hi << 16) |
(uint16) itup->t_tid.ip_blkid.bi_lo)), (uint16) itup->t_tid.ip_blkid.bi_lo)),
itup->t_tid.ip_posid, (int) IndexTupleSize (itup), itup->t_tid.ip_posid,
IndexTupleHasNulls (itup), IndexTupleHasVarwidths (itup)); (int) IndexTupleSize(itup),
IndexTupleHasNulls(itup) ? 1 : 0,
IndexTupleHasVarwidths(itup) ? 1 : 0);
if (numBytes != IndexTupleSize (itup)) if (numBytes != IndexTupleSize (itup))
printf (" Error: Item size difference. Given <%u>, " printf (" Error: Item size difference. Given <%u>, "
"Internal <%d>.\n", numBytes, (int) IndexTupleSize (itup)); "Internal <%d>.\n", numBytes, (int) IndexTupleSize (itup));
} }
} }
else if (formatAs == ITEM_SPG_INNER)
{
// It is an SpGistInnerTuple item, so dump the index header
if (numBytes < SGITHDRSZ)
{
if (numBytes)
printf (" Error: This item does not look like an SPGiST item.\n");
}
else else
{ {
// It is a heap item, so dump the heap header SpGistInnerTuple itup = (SpGistInnerTuple) (&(buffer[startIndex]));
printf (" State: %s allTheSame: %d nNodes: %u prefixSize: %u\n\n",
spgist_tupstates[itup->tupstate],
itup->allTheSame,
itup->nNodes,
itup->prefixSize);
if (numBytes != itup->size)
printf (" Error: Item size difference. Given <%u>, "
"Internal <%d>.\n", numBytes, (int) itup->size);
else if (itup->prefixSize == MAXALIGN(itup->prefixSize))
{
int i;
SpGistNodeTuple node;
// Dump the prefix contents in hex and ascii
if ((blockOptions & BLOCK_FORMAT) &&
SGITHDRSZ + itup->prefixSize <= numBytes)
FormatBinary (SGITHDRSZ + itup->prefixSize, startIndex);
// Try to print the nodes, but only while pointer is sane
SGITITERATE(itup, i, node)
{
int off = (char *) node - (char *) itup;
if (off + SGNTHDRSZ > numBytes)
break;
printf (" Node %2u: Downlink: %u/%u Size: %d Null: %u\n",
i,
((uint32) ((node->t_tid.ip_blkid.bi_hi << 16) |
(uint16) node->t_tid.ip_blkid.bi_lo)),
node->t_tid.ip_posid,
(int) IndexTupleSize(node),
IndexTupleHasNulls(node) ? 1 : 0);
// Dump the node's contents in hex and ascii
if ((blockOptions & BLOCK_FORMAT) &&
off + IndexTupleSize(node) <= numBytes)
FormatBinary (IndexTupleSize(node), startIndex + off);
if (IndexTupleSize(node) != MAXALIGN(IndexTupleSize(node)))
break;
}
}
printf ("\n");
}
}
else if (formatAs == ITEM_SPG_LEAF)
{
// It is an SpGistLeafTuple item, so dump the index header
if (numBytes < SGLTHDRSZ)
{
if (numBytes)
printf (" Error: This item does not look like an SPGiST item.\n");
}
else
{
SpGistLeafTuple itup = (SpGistLeafTuple) (&(buffer[startIndex]));
printf (" State: %s nextOffset: %u Block Id: %u linp Index: %u\n\n",
spgist_tupstates[itup->tupstate],
itup->nextOffset,
((uint32) ((itup->heapPtr.ip_blkid.bi_hi << 16) |
(uint16) itup->heapPtr.ip_blkid.bi_lo)),
itup->heapPtr.ip_posid);
if (numBytes != itup->size)
printf (" Error: Item size difference. Given <%u>, "
"Internal <%d>.\n", numBytes, (int) itup->size);
}
}
else
{
// It is a HeapTuple item, so dump the heap header
int alignedSize = MAXALIGN (sizeof (HeapTupleHeaderData)); int alignedSize = MAXALIGN (sizeof (HeapTupleHeaderData));
if (numBytes < alignedSize) if (numBytes < alignedSize)
@ -809,7 +933,7 @@ FormatItem (unsigned int numBytes, unsigned int startIndex,
printf (" XMIN: %u XMAX: %u CID|XVAC: %u", printf (" XMIN: %u XMAX: %u CID|XVAC: %u",
HeapTupleHeaderGetXmin(htup), HeapTupleHeaderGetXmin(htup),
HeapTupleHeaderGetXmax(htup), HeapTupleHeaderGetRawXmax(htup),
HeapTupleHeaderGetRawCommandId(htup)); HeapTupleHeaderGetRawCommandId(htup));
if (infoMask & HEAP_HASOID) if (infoMask & HEAP_HASOID)
@ -834,12 +958,14 @@ FormatItem (unsigned int numBytes, unsigned int startIndex,
strcat (flagString, "HASEXTERNAL|"); strcat (flagString, "HASEXTERNAL|");
if (infoMask & HEAP_HASOID) if (infoMask & HEAP_HASOID)
strcat (flagString, "HASOID|"); strcat (flagString, "HASOID|");
if (infoMask & HEAP_XMAX_KEYSHR_LOCK)
strcat (flagString, "XMAX_KEYSHR_LOCK|");
if (infoMask & HEAP_COMBOCID) if (infoMask & HEAP_COMBOCID)
strcat (flagString, "COMBOCID|"); strcat (flagString, "COMBOCID|");
if (infoMask & HEAP_XMAX_EXCL_LOCK) if (infoMask & HEAP_XMAX_EXCL_LOCK)
strcat (flagString, "XMAX_EXCL_LOCK|"); strcat (flagString, "XMAX_EXCL_LOCK|");
if (infoMask & HEAP_XMAX_SHARED_LOCK) if (infoMask & HEAP_XMAX_LOCK_ONLY)
strcat (flagString, "XMAX_SHARED_LOCK|"); strcat (flagString, "XMAX_LOCK_ONLY|");
if (infoMask & HEAP_XMIN_COMMITTED) if (infoMask & HEAP_XMIN_COMMITTED)
strcat (flagString, "XMIN_COMMITTED|"); strcat (flagString, "XMIN_COMMITTED|");
if (infoMask & HEAP_XMIN_INVALID) if (infoMask & HEAP_XMIN_INVALID)
@ -857,6 +983,8 @@ FormatItem (unsigned int numBytes, unsigned int startIndex,
if (infoMask & HEAP_MOVED_IN) if (infoMask & HEAP_MOVED_IN)
strcat (flagString, "MOVED_IN|"); strcat (flagString, "MOVED_IN|");
if (infoMask2 & HEAP_KEYS_UPDATED)
strcat (flagString, "KEYS_UPDATED|");
if (infoMask2 & HEAP_HOT_UPDATED) if (infoMask2 & HEAP_HOT_UPDATED)
strcat (flagString, "HOT_UPDATED|"); strcat (flagString, "HOT_UPDATED|");
if (infoMask2 & HEAP_ONLY_TUPLE) if (infoMask2 & HEAP_ONLY_TUPLE)
@ -903,9 +1031,8 @@ FormatItem (unsigned int numBytes, unsigned int startIndex,
} }
// On blocks that have special sections, we have to interpret the // On blocks that have special sections, print the contents
// contents based on size of the special section (since there is // according to previously determined special section type
// no other way)
static void static void
FormatSpecial () FormatSpecial ()
{ {
@ -997,6 +1124,8 @@ FormatSpecial ()
strcat (flagString, "DELETED|"); strcat (flagString, "DELETED|");
if (gistSection->flags & F_TUPLES_DELETED) if (gistSection->flags & F_TUPLES_DELETED)
strcat (flagString, "TUPLES_DELETED|"); strcat (flagString, "TUPLES_DELETED|");
if (gistSection->flags & F_FOLLOW_RIGHT)
strcat (flagString, "FOLLOW_RIGHT|");
if (strlen (flagString)) if (strlen (flagString))
flagString[strlen (flagString) - 1] = '\0'; flagString[strlen (flagString) - 1] = '\0';
printf (" GIST Index Section:\n" printf (" GIST Index Section:\n"
@ -1019,6 +1148,12 @@ FormatSpecial ()
strcat (flagString, "LEAF|"); strcat (flagString, "LEAF|");
if (ginSection->flags & GIN_DELETED) if (ginSection->flags & GIN_DELETED)
strcat (flagString, "DELETED|"); strcat (flagString, "DELETED|");
if (ginSection->flags & GIN_META)
strcat (flagString, "META|");
if (ginSection->flags & GIN_LIST)
strcat (flagString, "LIST|");
if (ginSection->flags & GIN_LIST_FULLROW)
strcat (flagString, "FULLROW|");
if (strlen (flagString)) if (strlen (flagString))
flagString[strlen (flagString) - 1] = '\0'; flagString[strlen (flagString) - 1] = '\0';
printf (" GIN Index Section:\n" printf (" GIN Index Section:\n"
@ -1030,6 +1165,30 @@ FormatSpecial ()
} }
break; break;
// SP-GIST index section
case SPEC_SECT_INDEX_SPGIST:
{
SpGistPageOpaque spgistSection = (SpGistPageOpaque) (buffer + specialOffset);
if (spgistSection->flags & SPGIST_META)
strcat (flagString, "META|");
if (spgistSection->flags & SPGIST_DELETED)
strcat (flagString, "DELETED|");
if (spgistSection->flags & SPGIST_LEAF)
strcat (flagString, "LEAF|");
if (spgistSection->flags & SPGIST_NULLS)
strcat (flagString, "NULLS|");
if (strlen (flagString))
flagString[strlen (flagString) - 1] = '\0';
printf (" SPGIST Index Section:\n"
" Flags: 0x%08x (%s)\n"
" nRedirection: %d\n"
" nPlaceholder: %d\n\n",
spgistSection->flags, flagString,
spgistSection->nRedirection,
spgistSection->nPlaceholder);
}
break;
// No idea what type of special section this is // No idea what type of special section this is
default: default:
printf (" Unknown special section type. Type: <%u>.\n", specialType); printf (" Unknown special section type. Type: <%u>.\n", specialType);
@ -1088,6 +1247,8 @@ FormatControl ()
{ {
unsigned int localPgVersion = 0; unsigned int localPgVersion = 0;
unsigned int controlFileSize = 0; unsigned int controlFileSize = 0;
time_t cd_time;
time_t cp_time;
printf printf
("\n<pg_control Contents> *********************************************\n\n"); ("\n<pg_control Contents> *********************************************\n\n");
@ -1144,6 +1305,10 @@ FormatControl ()
break; break;
} }
/* convert timestamps to system's time_t width */
cd_time = controlData->time;
cp_time = checkPoint->time;
printf (" CRC: %s\n" printf (" CRC: %s\n"
" pg_control Version: %u%s\n" " pg_control Version: %u%s\n"
" Catalog Version: %u\n" " Catalog Version: %u\n"
@ -1178,16 +1343,16 @@ FormatControl ()
controlData->catalog_version_no, controlData->catalog_version_no,
controlData->system_identifier, controlData->system_identifier,
dbState, dbState,
ctime (&(controlData->time)), ctime (&(cd_time)),
controlData->checkPoint.xlogid, controlData->checkPoint.xrecoff, (uint32) (controlData->checkPoint >> 32), (uint32) controlData->checkPoint,
controlData->prevCheckPoint.xlogid, controlData->prevCheckPoint.xrecoff, (uint32) (controlData->prevCheckPoint >> 32), (uint32) controlData->prevCheckPoint,
checkPoint->redo.xlogid, checkPoint->redo.xrecoff, (uint32) (checkPoint->redo >> 32), (uint32) checkPoint->redo,
checkPoint->ThisTimeLineID, checkPoint->ThisTimeLineID,
checkPoint->nextXidEpoch, checkPoint->nextXid, checkPoint->nextXidEpoch, checkPoint->nextXid,
checkPoint->nextOid, checkPoint->nextOid,
checkPoint->nextMulti, checkPoint->nextMultiOffset, checkPoint->nextMulti, checkPoint->nextMultiOffset,
ctime (&checkPoint->time), ctime (&cp_time),
controlData->minRecoveryPoint.xlogid, controlData->minRecoveryPoint.xrecoff, (uint32) (controlData->minRecoveryPoint >> 32), (uint32) controlData->minRecoveryPoint,
controlData->maxAlign, controlData->maxAlign,
controlData->floatFormat, controlData->floatFormat,
(controlData->floatFormat == FLOATFORMAT_VALUE ? (controlData->floatFormat == FLOATFORMAT_VALUE ?

View File

@ -1,9 +1,9 @@
/* /*
* pg_filedump.h - PostgreSQL file dump utility for dumping and * pg_filedump.h - PostgreSQL file dump utility for dumping and
* formatting heap (data), index and control files. * formatting heap (data), index and control files.
* Version 9.0.0 for PostgreSQL 9.0
* *
* Copyright (c) 2002-2010 Red Hat, Inc. All rights reserved. * Copyright (c) 2002-2010 Red Hat, Inc.
* Copyright (c) 2011-2014, PostgreSQL Global Development Group
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,25 +19,27 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* Author: Patrick Macdonald <patrickm@redhat.com> * Original Author: Patrick Macdonald <patrickm@redhat.com>
*
* Component of: PostgreSQL - Red Hat Edition - Utilities / Tools
*
*/ */
#include <stdio.h> #define FD_VERSION "9.3.0" /* version ID of pg_filedump */
#define FD_PG_VERSION "PostgreSQL 9.3.x" /* PG version it works with */
#include "postgres.h"
#include <time.h> #include <time.h>
#include <ctype.h> #include <ctype.h>
#include "postgres.h" #include "access/gin_private.h"
#include "storage/bufpage.h"
#include "access/hash.h"
#include "access/gin.h"
#include "access/gist.h" #include "access/gist.h"
#include "access/nbtree.h" #include "access/hash.h"
#include "access/itup.h"
#include "access/htup.h" #include "access/htup.h"
#include "access/htup_details.h"
#include "access/itup.h"
#include "access/nbtree.h"
#include "access/spgist_private.h"
#include "catalog/pg_control.h" #include "catalog/pg_control.h"
#include "storage/bufpage.h"
// Options for Block formatting operations // Options for Block formatting operations
static unsigned int blockOptions = 0; static unsigned int blockOptions = 0;
@ -60,8 +62,10 @@ static unsigned int itemOptions = 0;
typedef enum typedef enum
{ {
ITEM_DETAIL = 0x00000001, // -i: Display interpreted items ITEM_DETAIL = 0x00000001, // -i: Display interpreted items
ITEM_HEAP = 0x00000002, // -y: Blocks contain heap items ITEM_HEAP = 0x00000002, // -y: Blocks contain HeapTuple items
ITEM_INDEX = 0x00000004 // -x: Blocks contain index items ITEM_INDEX = 0x00000004, // -x: Blocks contain IndexTuple items
ITEM_SPG_INNER = 0x00000008, // Blocks contain SpGistInnerTuple items
ITEM_SPG_LEAF = 0x00000010 // Blocks contain SpGistLeafTuple items
} }
itemSwitches; itemSwitches;
@ -84,6 +88,7 @@ typedef enum
SPEC_SECT_INDEX_HASH, // Hash index info in special section SPEC_SECT_INDEX_HASH, // Hash index info in special section
SPEC_SECT_INDEX_GIST, // GIST index info in special section SPEC_SECT_INDEX_GIST, // GIST index info in special section
SPEC_SECT_INDEX_GIN, // GIN index info in special section SPEC_SECT_INDEX_GIN, // GIN index info in special section
SPEC_SECT_INDEX_SPGIST, // SP-GIST index info in special section
SPEC_SECT_ERROR_UNKNOWN, // Unknown error SPEC_SECT_ERROR_UNKNOWN, // Unknown error
SPEC_SECT_ERROR_BOUNDARY // Boundary error SPEC_SECT_ERROR_BOUNDARY // Boundary error
} }