Code

Some speedups - both of the SQL backends can handle using only one cursor.
[roundup.git] / roundup / backends / back_sqlite.py
1 # $Id: back_sqlite.py,v 1.4 2002-09-23 06:48:35 richard Exp $
2 __doc__ = '''
3 See https://pysqlite.sourceforge.net/ for pysqlite info
4 '''
5 import base64, marshal
6 from roundup.backends.rdbms_common import *
7 import sqlite
9 class Database(Database):
10     # char to use for positional arguments
11     arg = '%s'
13     def open_connection(self):
14         # ensure files are group readable and writable
15         os.umask(0002)
16         db = os.path.join(self.config.DATABASE, 'db')
17         self.conn = sqlite.connect(db=db)
18         self.cursor = self.conn.cursor()
19         try:
20             self.database_schema = self.load_dbschema()
21         except sqlite.DatabaseError, error:
22             if str(error) != 'no such table: schema':
23                 raise
24             self.database_schema = {}
25             self.cursor.execute('create table schema (schema varchar)')
26             self.cursor.execute('create table ids (name varchar, num integer)')
28     def __repr__(self):
29         return '<roundlite 0x%x>'%id(self)
31     def sql_fetchone(self):
32         ''' Fetch a single row. If there's nothing to fetch, return None.
33         '''
34         return self.cursor.fetchone()
36     def sql_commit(self):
37         ''' Actually commit to the database.
39             Ignore errors if there's nothing to commit.
40         '''
41         try:
42             self.conn.commit()
43         except sqlite.DatabaseError, error:
44             if str(error) != 'cannot commit - no transaction is active':
45                 raise
47     def save_dbschema(self, schema):
48         ''' Save the schema definition that the database currently implements
49         '''
50         s = repr(self.database_schema)
51         self.sql('insert into schema values (%s)', (s,))
53     def load_dbschema(self):
54         ''' Load the schema definition that the database currently implements
55         '''
56         self.cursor.execute('select schema from schema')
57         return eval(self.cursor.fetchone()[0])
59     def save_journal(self, classname, cols, nodeid, journaldate,
60             journaltag, action, params):
61         ''' Save the journal entry to the database
62         '''
63         # make the params db-friendly
64         params = repr(params)
65         entry = (nodeid, journaldate, journaltag, action, params)
67         # do the insert
68         a = self.arg
69         sql = 'insert into %s__journal (%s) values (%s,%s,%s,%s,%s)'%(classname,
70             cols, a, a, a, a, a)
71         if __debug__:
72             print >>hyperdb.DEBUG, 'addjournal', (self, sql, entry)
73         self.cursor.execute(sql, entry)
75     def load_journal(self, classname, cols, nodeid):
76         ''' Load the journal from the database
77         '''
78         # now get the journal entries
79         sql = 'select %s from %s__journal where nodeid=%s'%(cols, classname,
80             self.arg)
81         if __debug__:
82             print >>hyperdb.DEBUG, 'getjournal', (self, sql, nodeid)
83         self.cursor.execute(sql, (nodeid,))
84         res = []
85         for nodeid, date_stamp, user, action, params in self.cursor.fetchall():
86             params = eval(params)
87             res.append((nodeid, date.Date(date_stamp), user, action, params))
88         return res
90     def unserialise(self, classname, node):
91         ''' Decode the marshalled node data
93             SQLite stringifies _everything_... so we need to re-numberificate
94             Booleans and Numbers.
95         '''
96         if __debug__:
97             print >>hyperdb.DEBUG, 'unserialise', classname, node
98         properties = self.getclass(classname).getprops()
99         d = {}
100         for k, v in node.items():
101             # if the property doesn't exist, or is the "retired" flag then
102             # it won't be in the properties dict
103             if not properties.has_key(k):
104                 d[k] = v
105                 continue
107             # get the property spec
108             prop = properties[k]
110             if isinstance(prop, Date) and v is not None:
111                 d[k] = date.Date(v)
112             elif isinstance(prop, Interval) and v is not None:
113                 d[k] = date.Interval(v)
114             elif isinstance(prop, Password):
115                 p = password.Password()
116                 p.unpack(v)
117                 d[k] = p
118             elif isinstance(prop, Boolean) and v is not None:
119                 d[k] = int(v)
120             elif isinstance(prop, Number) and v is not None:
121                 # try int first, then assume it's a float
122                 try:
123                     d[k] = int(v)
124                 except ValueError:
125                     d[k] = float(v)
126             else:
127                 d[k] = v
128         return d