Support decoding of catalog tables.
authorTeodor Sigaev <[email protected]>
Wed, 1 Mar 2017 12:08:09 +0000 (15:08 +0300)
committerTeodor Sigaev <[email protected]>
Wed, 1 Mar 2017 12:08:09 +0000 (15:08 +0300)
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

README.pg_filedump
decode.c
pg_filedump.c

index 723ae5513fe9f75f2a2038c8492621afd7ca7820..cf3f703619543abb3589678a5571d072824d96b8 100644 (file)
@@ -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
index 4da4c7c55f3ec8b1ffe13341c83fce0e8834d05d..7afa273b978e0f571284efe5da58b003ac65ebb7 100644 (file)
--- a/decode.c
+++ b/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)
index fc02cc6f1b58a6dd53184651eb753c63d3a80390..ccc7ebaa0215988e7f924bd09dd7e1b43bb2c53e 100644 (file)
@@ -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)