Support decoding of catalog tables.
Support decoding of 'name' and 'char' types. Also introduce '~' pseudo-type which just ignores all data left in current tuple during decoding. These two types allow easily to decode catalog tables and restore schema of a database even if it's corrupted and PostgreSQL instance is not starting. For instance, pg_attribute can be decoded like this: pg_filedump -D oid,name,oid,int,smallint,~ path/to/segment/1249 Aleksander Alekseev
This commit is contained in:
parent
52fa0201f9
commit
5c5ba458fa
@ -71,8 +71,36 @@ The following options are valid for heap and index files:
|
||||
off all formatting options)
|
||||
-d Display formatted block content dump (Option will turn off
|
||||
all other formatting options)
|
||||
-D Try to decode tuples using provided list of attribute types.
|
||||
[attrlist] should be something like int,timestamp,bool,uuid
|
||||
-D Try to decode tuples using given comma separated list of types.
|
||||
List of supported types:
|
||||
* bigint
|
||||
* bigserial
|
||||
* bool
|
||||
* char
|
||||
* charN -- char(n)
|
||||
* date
|
||||
* float
|
||||
* float4
|
||||
* float8
|
||||
* int
|
||||
* json
|
||||
* macaddr
|
||||
* name
|
||||
* oid
|
||||
* real
|
||||
* serial
|
||||
* smallint
|
||||
* smallserial
|
||||
* text
|
||||
* time
|
||||
* timestamp
|
||||
* timetz
|
||||
* uuid
|
||||
* varchar
|
||||
* varcharN -- varchar(n)
|
||||
* xid
|
||||
* xml
|
||||
* ~ -- ignores are attributes left in a tuple
|
||||
-f Display formatted block content dump along with interpretation
|
||||
-h Display this information
|
||||
-i Display interpreted item details
|
||||
|
59
decode.c
59
decode.c
@ -54,6 +54,15 @@ decode_macaddr(const char* buffer, unsigned int buff_size, unsigned int* out_siz
|
||||
static int
|
||||
decode_string(const char* buffer, unsigned int buff_size, unsigned int* out_size);
|
||||
|
||||
static int
|
||||
decode_char(const char* buffer, unsigned int buff_size, unsigned int* out_size);
|
||||
|
||||
static int
|
||||
decode_name(const char* buffer, unsigned int buff_size, unsigned int* out_size);
|
||||
|
||||
static int
|
||||
decode_ignore(const char* buffer, unsigned int buff_size, unsigned int* out_size);
|
||||
|
||||
static int ncallbacks = 0;
|
||||
static decode_callback_t callbacks[ATTRTYPES_STR_MAX_LEN / 2] = { NULL };
|
||||
|
||||
@ -66,6 +75,8 @@ static ParseCallbackTableItem callback_table[] = {
|
||||
{ "smallserial", &decode_smallint },
|
||||
{ "smallint", &decode_smallint },
|
||||
{ "int", &decode_int },
|
||||
{ "oid", &decode_int },
|
||||
{ "xid", &decode_int },
|
||||
{ "serial", &decode_int },
|
||||
{ "bigint", &decode_bigint },
|
||||
{ "bigserial", &decode_bigint },
|
||||
@ -73,16 +84,21 @@ static ParseCallbackTableItem callback_table[] = {
|
||||
{ "timetz", &decode_timetz },
|
||||
{ "date", &decode_date },
|
||||
{ "timestamp", &decode_timestamp },
|
||||
{ "real", &decode_float4 },
|
||||
{ "float4", &decode_float4 },
|
||||
{ "float8", &decode_float8 },
|
||||
{ "float", &decode_float8 },
|
||||
{ "bool", &decode_bool },
|
||||
{ "uuid", &decode_uuid },
|
||||
{ "macaddr", &decode_macaddr },
|
||||
{ "name", &decode_name },
|
||||
{ "char", &decode_char },
|
||||
{ "~", &decode_ignore },
|
||||
|
||||
/* internally all string types are stored the same way */
|
||||
{ "char", &decode_string },
|
||||
{ "charN", &decode_string },
|
||||
{ "varchar", &decode_string },
|
||||
{ "varcharN", &decode_string },
|
||||
{ "text", &decode_string },
|
||||
{ "json", &decode_string },
|
||||
{ "xml", &decode_string },
|
||||
@ -654,6 +670,47 @@ decode_bool(const char* buffer, unsigned int buff_size, unsigned int* out_size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decode a name type (used mostly in catalog tables) */
|
||||
static int
|
||||
decode_name(const char* buffer, unsigned int buff_size, unsigned int* out_size)
|
||||
{
|
||||
const char* new_buffer = (const char*)TYPEALIGN(sizeof(uint32), (uintptr_t)buffer);
|
||||
unsigned int delta = (unsigned int)( (uintptr_t)new_buffer - (uintptr_t)buffer );
|
||||
|
||||
if(buff_size < delta)
|
||||
return -1;
|
||||
|
||||
buff_size -= delta;
|
||||
buffer = new_buffer;
|
||||
|
||||
if(buff_size < NAMEDATALEN)
|
||||
return -2;
|
||||
|
||||
CopyAppendEncode(buffer, strnlen(buffer, NAMEDATALEN));
|
||||
*out_size = NAMEDATALEN + delta;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decode a char type */
|
||||
static int
|
||||
decode_char(const char* buffer, unsigned int buff_size, unsigned int* out_size)
|
||||
{
|
||||
if(buff_size < sizeof(char))
|
||||
return -2;
|
||||
|
||||
CopyAppendEncode(buffer, 1);
|
||||
*out_size = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ignore all data left */
|
||||
static int
|
||||
decode_ignore(const char* buffer, unsigned int buff_size, unsigned int* out_size)
|
||||
{
|
||||
*out_size = buff_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decode char(N), varchar(N), text, json or xml types */
|
||||
static int
|
||||
decode_string(const char* buffer, unsigned int buff_size, unsigned int* out_size)
|
||||
|
@ -116,8 +116,8 @@ DisplayOptions(unsigned int validOptions)
|
||||
" off all formatting options)\n"
|
||||
" -d Display formatted block content dump (Option will turn off\n"
|
||||
" all other formatting options)\n"
|
||||
" -D Try to decode tuples using provided list of attribute types.\n"
|
||||
" [attrlist] should be something like int,timestamp,bool,uuid\n"
|
||||
" -D Try to decode tuples using given comma separated list of types.\n"
|
||||
" For full list of supported attribyte types see README file.\n"
|
||||
" -f Display formatted block content dump along with interpretation\n"
|
||||
" -h Display this information\n"
|
||||
" -i Display interpreted item details\n"
|
||||
@ -1002,7 +1002,7 @@ FormatItemBlock(Page page)
|
||||
FormatBinary(itemSize, itemOffset);
|
||||
|
||||
/* Decode tuple data */
|
||||
if(blockOptions & BLOCK_DECODE)
|
||||
if((blockOptions & BLOCK_DECODE) && (itemFlags == LP_NORMAL))
|
||||
FormatDecode(&buffer[itemOffset], itemSize);
|
||||
|
||||
if (x == maxOffset)
|
||||
|
Loading…
x
Reference in New Issue
Block a user