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]