comparison roundup/backends/back_sqlite.py @ 1911:f5c804379c85

fixed ZRoundup - mostly changes to classic template
author Richard Jones <richard@users.sourceforge.net>
date Wed, 12 Nov 2003 01:00:59 +0000
parents f255363e6d97
children fc52d57c6c3e
comparison
equal deleted inserted replaced
1910:d19fd344bd1f 1911:f5c804379c85
1 # $Id: back_sqlite.py,v 1.11 2003-11-11 11:19:18 richard Exp $ 1 # $Id: back_sqlite.py,v 1.12 2003-11-12 01:00:58 richard Exp $
2 __doc__ = ''' 2 __doc__ = '''
3 See https://pysqlite.sourceforge.net/ for pysqlite info 3 See https://pysqlite.sourceforge.net/ for pysqlite info
4 ''' 4 '''
5 import base64, marshal 5 import os, base64, marshal
6 from roundup.backends.rdbms_common import * 6
7 from roundup import hyperdb
8 from roundup.backends import rdbms_common
7 from roundup.backends import locking 9 from roundup.backends import locking
8 import sqlite 10 import sqlite
9 11
10 class Database(Database): 12 class Database(rdbms_common.Database):
11 # char to use for positional arguments 13 # char to use for positional arguments
12 arg = '%s' 14 arg = '%s'
13 15
14 def open_connection(self): 16 def sql_open_connection(self):
15 # ensure files are group readable and writable 17 # ensure files are group readable and writable
16 os.umask(0002) 18 os.umask(0002)
17 db = os.path.join(self.config.DATABASE, 'db') 19 db = os.path.join(self.config.DATABASE, 'db')
18 20
19 # lock it 21 # lock it
32 self.database_schema = {} 34 self.database_schema = {}
33 self.cursor.execute('create table schema (schema varchar)') 35 self.cursor.execute('create table schema (schema varchar)')
34 self.cursor.execute('create table ids (name varchar, num integer)') 36 self.cursor.execute('create table ids (name varchar, num integer)')
35 self.cursor.execute('create index ids_name_idx on ids(name)') 37 self.cursor.execute('create index ids_name_idx on ids(name)')
36 38
37 def close(self): 39 def sql_close(self):
38 ''' Close off the connection. 40 ''' Squash any error caused by us already having closed the
39
40 Squash any error caused by us already having closed the
41 connection. 41 connection.
42 ''' 42 '''
43 try: 43 try:
44 self.conn.close() 44 self.conn.close()
45 except sqlite.ProgrammingError, value: 45 except sqlite.ProgrammingError, value:
46 if str(value) != 'close failed - Connection is closed.': 46 if str(value) != 'close failed - Connection is closed.':
47 raise 47 raise
48 48
49 # release the lock too 49 def sql_rollback(self):
50 if self.lockfile is not None: 50 ''' Squash any error caused by us having closed the connection (and
51 locking.release_lock(self.lockfile)
52 if self.lockfile is not None:
53 self.lockfile.close()
54 self.lockfile = None
55
56 def rollback(self):
57 ''' Reverse all actions from the current transaction.
58
59 Undo all the changes made since the database was opened or the
60 last commit() or rollback() was performed.
61
62 Squash any error caused by us having closed the connection (and
63 therefore not having anything to roll back) 51 therefore not having anything to roll back)
64 ''' 52 '''
65 if __debug__:
66 print >>hyperdb.DEBUG, 'rollback', (self,)
67
68 # roll back
69 try: 53 try:
70 self.conn.rollback() 54 self.conn.rollback()
71 except sqlite.ProgrammingError, value: 55 except sqlite.ProgrammingError, value:
72 if str(value) != 'rollback failed - Connection is closed.': 56 if str(value) != 'rollback failed - Connection is closed.':
73 raise 57 raise
74 58
75 # roll back "other" transaction stuff
76 for method, args in self.transactions:
77 # delete temporary files
78 if method == self.doStoreFile:
79 self.rollbackStoreFile(*args)
80 self.transactions = []
81
82 # clear the cache
83 self.clearCache()
84
85 def __repr__(self): 59 def __repr__(self):
86 return '<roundlite 0x%x>'%id(self) 60 return '<roundlite 0x%x>'%id(self)
87
88 def sql_fetchone(self):
89 ''' Fetch a single row. If there's nothing to fetch, return None.
90 '''
91 return self.cursor.fetchone()
92
93 def sql_fetchall(self):
94 ''' Fetch a single row. If there's nothing to fetch, return [].
95 '''
96 return self.cursor.fetchall()
97 61
98 def sql_commit(self): 62 def sql_commit(self):
99 ''' Actually commit to the database. 63 ''' Actually commit to the database.
100 64
101 Ignore errors if there's nothing to commit. 65 Ignore errors if there's nothing to commit.
111 for entry in self.cursor.fetchall(): 75 for entry in self.cursor.fetchall():
112 if entry[1] == index_name: 76 if entry[1] == index_name:
113 return 1 77 return 1
114 return 0 78 return 0
115 79
116 def save_dbschema(self, schema): 80 class sqliteClass:
117 ''' Save the schema definition that the database currently implements 81 def filter(self, search_matches, filterspec, sort=(None,None),
82 group=(None,None)):
83 ''' If there's NO matches to a fetch, sqlite returns NULL
84 instead of nothing
118 ''' 85 '''
119 s = repr(self.database_schema) 86 return filter(None, rdbms_common.Class.filter(self, search_matches,
120 self.sql('insert into schema values (%s)', (s,)) 87 filterspec, sort=sort, group=group))
121 88
122 def load_dbschema(self): 89 class Class(sqliteClass, rdbms_common.Class):
123 ''' Load the schema definition that the database currently implements 90 pass
124 '''
125 self.cursor.execute('select schema from schema')
126 return eval(self.cursor.fetchone()[0])
127 91
128 def save_journal(self, classname, cols, nodeid, journaldate, 92 class IssueClass(sqliteClass, rdbms_common.IssueClass):
129 journaltag, action, params): 93 pass
130 ''' Save the journal entry to the database
131 '''
132 # make the params db-friendly
133 params = repr(params)
134 entry = (nodeid, journaldate, journaltag, action, params)
135 94
136 # do the insert 95 class FileClass(sqliteClass, rdbms_common.FileClass):
137 a = self.arg 96 pass
138 sql = 'insert into %s__journal (%s) values (%s,%s,%s,%s,%s)'%(classname,
139 cols, a, a, a, a, a)
140 if __debug__:
141 print >>hyperdb.DEBUG, 'addjournal', (self, sql, entry)
142 self.cursor.execute(sql, entry)
143 97
144 def load_journal(self, classname, cols, nodeid):
145 ''' Load the journal from the database
146 '''
147 # now get the journal entries
148 sql = 'select %s from %s__journal where nodeid=%s'%(cols, classname,
149 self.arg)
150 if __debug__:
151 print >>hyperdb.DEBUG, 'getjournal', (self, sql, nodeid)
152 self.cursor.execute(sql, (nodeid,))
153 res = []
154 for nodeid, date_stamp, user, action, params in self.cursor.fetchall():
155 params = eval(params)
156 res.append((nodeid, date.Date(date_stamp), user, action, params))
157 return res
158 98
159 def unserialise(self, classname, node):
160 ''' Decode the marshalled node data
161
162 SQLite stringifies _everything_... so we need to re-numberificate
163 Booleans and Numbers.
164 '''
165 if __debug__:
166 print >>hyperdb.DEBUG, 'unserialise', classname, node
167 properties = self.getclass(classname).getprops()
168 d = {}
169 for k, v in node.items():
170 # if the property doesn't exist, or is the "retired" flag then
171 # it won't be in the properties dict
172 if not properties.has_key(k):
173 d[k] = v
174 continue
175
176 # get the property spec
177 prop = properties[k]
178
179 if isinstance(prop, Date) and v is not None:
180 d[k] = date.Date(v)
181 elif isinstance(prop, Interval) and v is not None:
182 d[k] = date.Interval(v)
183 elif isinstance(prop, Password) and v is not None:
184 p = password.Password()
185 p.unpack(v)
186 d[k] = p
187 elif isinstance(prop, Boolean) and v is not None:
188 d[k] = int(v)
189 elif isinstance(prop, Number) and v is not None:
190 # try int first, then assume it's a float
191 try:
192 d[k] = int(v)
193 except ValueError:
194 d[k] = float(v)
195 else:
196 d[k] = v
197 return d
198

Roundup Issue Tracker: http://roundup-tracker.org/