Code

display _some_ text even when the link isn't interesting
[roundup.git] / roundup / backends / back_sqlite.py
1 # $Id: back_sqlite.py,v 1.7 2002-10-08 04:11:16 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 close(self):
29         ''' Close off the connection.
31             Squash any error caused by us already having closed the
32             connection.
33         '''
34         try:
35             self.conn.close()
36         except sqlite.ProgrammingError, value:
37             if str(value) != 'close failed - Connection is closed.':
38                 raise
41     def rollback(self):
42         ''' Reverse all actions from the current transaction.
44             Undo all the changes made since the database was opened or the
45             last commit() or rollback() was performed.
47             Squash any error caused by us having closed the connection (and
48             therefore not having anything to roll back)
49         '''
50         if __debug__:
51             print >>hyperdb.DEBUG, 'rollback', (self,)
53         # roll back
54         try:
55             self.conn.rollback()
56         except sqlite.ProgrammingError, value:
57             if str(value) != 'rollback failed - Connection is closed.':
58                 raise
60         # roll back "other" transaction stuff
61         for method, args in self.transactions:
62             # delete temporary files
63             if method == self.doStoreFile:
64                 self.rollbackStoreFile(*args)
65         self.transactions = []
67     def __repr__(self):
68         return '<roundlite 0x%x>'%id(self)
70     def sql_fetchone(self):
71         ''' Fetch a single row. If there's nothing to fetch, return None.
72         '''
73         return self.cursor.fetchone()
75     def sql_fetchall(self):
76         ''' Fetch a single row. If there's nothing to fetch, return [].
77         '''
78         return self.cursor.fetchall()
80     def sql_commit(self):
81         ''' Actually commit to the database.
83             Ignore errors if there's nothing to commit.
84         '''
85         try:
86             self.conn.commit()
87         except sqlite.DatabaseError, error:
88             if str(error) != 'cannot commit - no transaction is active':
89                 raise
91     def save_dbschema(self, schema):
92         ''' Save the schema definition that the database currently implements
93         '''
94         s = repr(self.database_schema)
95         self.sql('insert into schema values (%s)', (s,))
97     def load_dbschema(self):
98         ''' Load the schema definition that the database currently implements
99         '''
100         self.cursor.execute('select schema from schema')
101         return eval(self.cursor.fetchone()[0])
103     def save_journal(self, classname, cols, nodeid, journaldate,
104             journaltag, action, params):
105         ''' Save the journal entry to the database
106         '''
107         # make the params db-friendly
108         params = repr(params)
109         entry = (nodeid, journaldate, journaltag, action, params)
111         # do the insert
112         a = self.arg
113         sql = 'insert into %s__journal (%s) values (%s,%s,%s,%s,%s)'%(classname,
114             cols, a, a, a, a, a)
115         if __debug__:
116             print >>hyperdb.DEBUG, 'addjournal', (self, sql, entry)
117         self.cursor.execute(sql, entry)
119     def load_journal(self, classname, cols, nodeid):
120         ''' Load the journal from the database
121         '''
122         # now get the journal entries
123         sql = 'select %s from %s__journal where nodeid=%s'%(cols, classname,
124             self.arg)
125         if __debug__:
126             print >>hyperdb.DEBUG, 'getjournal', (self, sql, nodeid)
127         self.cursor.execute(sql, (nodeid,))
128         res = []
129         for nodeid, date_stamp, user, action, params in self.cursor.fetchall():
130             params = eval(params)
131             res.append((nodeid, date.Date(date_stamp), user, action, params))
132         return res
134     def unserialise(self, classname, node):
135         ''' Decode the marshalled node data
137             SQLite stringifies _everything_... so we need to re-numberificate
138             Booleans and Numbers.
139         '''
140         if __debug__:
141             print >>hyperdb.DEBUG, 'unserialise', classname, node
142         properties = self.getclass(classname).getprops()
143         d = {}
144         for k, v in node.items():
145             # if the property doesn't exist, or is the "retired" flag then
146             # it won't be in the properties dict
147             if not properties.has_key(k):
148                 d[k] = v
149                 continue
151             # get the property spec
152             prop = properties[k]
154             if isinstance(prop, Date) and v is not None:
155                 d[k] = date.Date(v)
156             elif isinstance(prop, Interval) and v is not None:
157                 d[k] = date.Interval(v)
158             elif isinstance(prop, Password) and v is not None:
159                 p = password.Password()
160                 p.unpack(v)
161                 d[k] = p
162             elif isinstance(prop, Boolean) and v is not None:
163                 d[k] = int(v)
164             elif isinstance(prop, Number) and v is not None:
165                 # try int first, then assume it's a float
166                 try:
167                     d[k] = int(v)
168                 except ValueError:
169                     d[k] = float(v)
170             else:
171                 d[k] = v
172         return d