On Wed, 2002-07-10 at 16:20, Lamar Owen wrote:
> On Wednesday 10 July 2002 09:11 am, Hannu Krosing wrote:
> > On Wed, 2002-07-10 at 01:09, Lamar Owen wrote:
> > > The wc utility isn't in the path in an OS install situation.  The df
> > > utility isn't in the path, either.  You can use python, though. :-)  Not
> > > that that would be a good thing in this context, however.
> 
> > Why not ?
> 
> > The following is wc in python
> 
> [snip]
> 
> > And I have written custom postgres table dumpers in python without too
> > much effort (except reverse-engineering the page structure ;) for both
> > 6.x and 7.x database tables, so we could actually use python here too.
> 
> I'm willing to look into this.  However, the dump still has to be pulled with 
> a standalone backend -- no networking availability can be assumed.

Actually it works on raw table file ;)

I attach code that dumps data from page file for table of 4 ints all NOT
NULL, like

create table fourints(
  i1 int not null,
  i2 int not null,
  i3 int not null,
  i4 int not null
);

the script is meant for quick and dirty resque operations, and requires
that one writes their own data-field extractor code. I have used it
mainly to resurrect accidentally deleted data.

it is for 7.x style pagefile layout

-------------------
Hannu

#!/usr/bin/python

import sys,os,struct,string

page_size = 8*1024

def strbits(s,len):
    bits = []
    while s:
        c = s[0]
        s = s[1:]
        b = struct.unpack('B',c)[0]
        for i in range(8):
            if b & (1<<i): bits.append(1)
            else: bits.append(0)
    return string.join(map(str,bits),'')[:len]

DEBUGPRINT = 0

class table_page:
    "class to represent a database table page"
    def __init__(self,fd,page_nr,dataconv):
        fd.seek(page_nr*page_size)
        self.rawdata = fd.read(page_size)
        if not self.rawdata:
            return
        self.lower,\
        self.upper,\
        self.special,\
        self.opaque = \
        struct.unpack('HHHH',self.rawdata[12:20])
        self.item_pointers=[]
        self.items=[]
        if DEBUGPRINT:
            print self.lower,self.upper,self.special,self.opaque
        for i in range(20,self.lower,4):
            rawItemIdData = self.rawdata[i:i+4]
            ItemIdData_I32 = struct.unpack('L',rawItemIdData)[0]
            if not ItemIdData_I32: break
            lp_len = int(ItemIdData_I32 >> 17)
            lp_flags = int((ItemIdData_I32 >> 15) & 3)
            lp_off = int(ItemIdData_I32 & 0x7fff)
            self.item_pointers.append((hex(ItemIdData_I32),lp_off,lp_flags,lp_len))
            rawItemData = self.rawdata[lp_off:lp_off+lp_len]
            t_oid,t_001,t_002,t_xmin,t_xmax,tid1,tid2,t_fcnt,t_xxx,t_doff = \
                struct.unpack('6L3HB', rawItemData[ 0: 31])
            t_ctid  = (tid1,tid2)
            t_mask = strbits(rawItemData[31:t_doff],t_fcnt)   
            raw_data = rawItemData[t_doff:]   
#            unpack 4 ints
            t_data = dataconv(raw_data,t_mask)
            self.items.append((t_oid,t_001,t_002,t_xmin,t_xmax,t_ctid,t_fcnt,t_xxx,t_doff,t_mask,t_data))
    def __str__(self):
         return string.join(map(repr,self.items),'\n')

if __name__=="__main__":
    site_base = "."
    db_name = ""
    table_name = "171617.16k"

    db_path = os.path.join(site_base,db_name)
    table_path = os.path.join(db_path,table_name)

    print table_path

    # this custom data converter must be written for each table
    # or derived from reading system tables

    def extract4ints(data,nullmask):
        return struct.unpack('LLLL', data)

    print '# dumping %s' % table_path
    fd = open(table_name)
    page_nr = 0
    while 1:
        page = table_page(fd,page_nr,extract4ints)
        if not page.rawdata: break
        print page
        page_nr = page_nr + 1
    print 'processed %d pages' % page_nr


---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]

Reply via email to