Preliminary support for SP-GiST indexes.
This commit is contained in:
parent
3551cfe252
commit
883c674f6f
180
pg_filedump.c
180
pg_filedump.c
@ -286,7 +286,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 +434,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 +465,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 +478,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
|
||||||
@ -687,10 +700,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
|
||||||
formatAs = ITEM_HEAP;
|
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;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (x = 1; x < (maxOffset + 1); x++)
|
for (x = 1; x < (maxOffset + 1); x++)
|
||||||
{
|
{
|
||||||
@ -754,9 +787,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)
|
||||||
@ -779,9 +819,86 @@ FormatItem (unsigned int numBytes, unsigned int startIndex,
|
|||||||
"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
|
||||||
|
{
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
// It is a heap item, so dump the heap header
|
// 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)
|
||||||
@ -908,9 +1025,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 ()
|
||||||
{
|
{
|
||||||
@ -1043,6 +1159,28 @@ 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 (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);
|
||||||
@ -1101,6 +1239,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");
|
||||||
@ -1157,6 +1297,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"
|
||||||
@ -1191,7 +1335,7 @@ 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,
|
controlData->checkPoint.xlogid, controlData->checkPoint.xrecoff,
|
||||||
controlData->prevCheckPoint.xlogid, controlData->prevCheckPoint.xrecoff,
|
controlData->prevCheckPoint.xlogid, controlData->prevCheckPoint.xrecoff,
|
||||||
checkPoint->redo.xlogid, checkPoint->redo.xrecoff,
|
checkPoint->redo.xlogid, checkPoint->redo.xrecoff,
|
||||||
@ -1199,7 +1343,7 @@ FormatControl ()
|
|||||||
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,
|
controlData->minRecoveryPoint.xlogid, controlData->minRecoveryPoint.xrecoff,
|
||||||
controlData->maxAlign,
|
controlData->maxAlign,
|
||||||
controlData->floatFormat,
|
controlData->floatFormat,
|
||||||
|
@ -22,21 +22,21 @@
|
|||||||
* Original Author: Patrick Macdonald <patrickm@redhat.com>
|
* Original Author: Patrick Macdonald <patrickm@redhat.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FD_VERSION "9.1.0" /* version ID of pg_filedump */
|
#define FD_VERSION "9.2.0" /* version ID of pg_filedump */
|
||||||
#define FD_PG_VERSION "PostgreSQL 9.1.x" /* PG version it works with */
|
#define FD_PG_VERSION "PostgreSQL 9.2.x" /* PG version it works with */
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "access/gin.h"
|
|
||||||
#include "access/gin_private.h"
|
#include "access/gin_private.h"
|
||||||
#include "access/gist.h"
|
#include "access/gist.h"
|
||||||
#include "access/hash.h"
|
#include "access/hash.h"
|
||||||
#include "access/htup.h"
|
#include "access/htup.h"
|
||||||
#include "access/itup.h"
|
#include "access/itup.h"
|
||||||
#include "access/nbtree.h"
|
#include "access/nbtree.h"
|
||||||
|
#include "access/spgist_private.h"
|
||||||
#include "catalog/pg_control.h"
|
#include "catalog/pg_control.h"
|
||||||
#include "storage/bufpage.h"
|
#include "storage/bufpage.h"
|
||||||
|
|
||||||
@ -61,8 +61,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;
|
||||||
|
|
||||||
@ -85,6 +87,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
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user