In-memory number array database
| 1 | import array, cPickle |
| 2 | |
| 3 | class pynumgrid: |
| 4 | 'In-memory number array database' |
| 5 | def __init__( self, schema=None, fname=None ): |
| 6 | '''schema -> 'field1:atype field2:atype ...' where atype is a |
| 7 | python array type code (see eg below)''' |
| 8 | if fname: |
| 9 | self.load( fname ) |
| 10 | else: |
| 11 | if type(schema) == str: |
| 12 | schema = [ f.split(':') for f in schema.split() ] |
| 13 | self.schema = schema |
| 14 | self.flist = [ f for f,t in schema ] |
| 15 | self.data = dict( [(f, array.array(t)) for f,t in schema] ) |
| 16 | self.rowcount = 0 |
| 17 | def insert( self, record, recnum=None ): |
| 18 | 'Insert one record (or append if no rec number)' |
| 19 | if recnum == None: |
| 20 | for i, value in enumerate( record ): |
| 21 | self.data[ self.flist[i] ].append( value ) |
| 22 | else: |
| 23 | for i, value in enumerate( record ): |
| 24 | self.data[ self.flist[i] ].insert( value, recnum ) |
| 25 | self.rowcount += 1 |
| 26 | def update( self, record, recnum ): |
| 27 | 'Change the record at recnum with updated values' |
| 28 | for i, value in enumerate( record ): |
| 29 | self.data[ self.flist[i] ][ recnum ] = value |
| 30 | def delete( self, recnum ): |
| 31 | 'Delete the record ar recnum, and return it' |
| 32 | record = [] |
| 33 | for field in self.flist: |
| 34 | record.append( self.data[ field ].pop( recnum ) ) |
| 35 | self.rowcount -= 1 |
| 36 | return record |
| 37 | def extend( self, colset ): |
| 38 | 'Add a set of columns to the database (fast)' |
| 39 | for i, col in enumerate( colset ): |
| 40 | self.data[ self.flist[i] ].extend( col ) |
| 41 | self.rowcount += len( colset[0] ) |
| 42 | def select( self, query, ns={} ): |
| 43 | 'Execute a python expression using data and ns namespace' |
| 44 | ns.update( dict( _en=enumerate, _rc=xrange(self.rowcount), |
| 45 | array=array.array ) ) |
| 46 | return eval( query, self.data, ns ) |
| 47 | def fetchlist( self, reclist, cols=[] ): |
| 48 | 'Return a list of records given a list of record numbers' |
| 49 | cols = cols or self.flist |
| 50 | colset = [ self.data[f] for f in cols ] |
| 51 | return [ [d[i] for d in colset] for i in reclist ] |
| 52 | def save( self, fname ): |
| 53 | 'Write the db to disk files (FAST!)' |
| 54 | cfg = (self.schema, self.rowcount) |
| 55 | cPickle.dump( cfg, open(fname+'.cfg','wb'), -1 ) |
| 56 | for field in self.flist: |
| 57 | fh = open( '%s__%s.dat' % (fname,field), 'wb' ) |
| 58 | self.data[ field ].tofile( fh ) |
| 59 | def load( self, fname ): |
| 60 | 'Read and/or build db on to this database (FAST!)' |