X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=roundup%2Fbackends%2Fback_sqlite.py;h=69d258523dbd1e335b435b710c0775b18bce85b2;hb=caa5cbb02293756565461df92b1a36f04c8ea782;hp=6f1f3590178c00b9b00fde3fe46946dcb2790b03;hpb=8cae7869d7bbde4750aaef094b58d3c0ba0571bf;p=roundup.git diff --git a/roundup/backends/back_sqlite.py b/roundup/backends/back_sqlite.py index 6f1f359..69d2585 100644 --- a/roundup/backends/back_sqlite.py +++ b/roundup/backends/back_sqlite.py @@ -1,9 +1,10 @@ -# $Id: back_sqlite.py,v 1.2 2002-09-18 07:04:37 richard Exp $ +# $Id: back_sqlite.py,v 1.8 2002-12-12 09:31:04 richard Exp $ __doc__ = ''' See https://pysqlite.sourceforge.net/ for pysqlite info ''' import base64, marshal from roundup.backends.rdbms_common import * +from roundup.backends import locking import sqlite class Database(Database): @@ -14,25 +15,81 @@ class Database(Database): # ensure files are group readable and writable os.umask(0002) db = os.path.join(self.config.DATABASE, 'db') + + # lock it + lockfilenm = db[:-3] + 'lck' + self.lockfile = locking.acquire_lock(lockfilenm) + self.lockfile.write(str(os.getpid())) + self.lockfile.flush() + self.conn = sqlite.connect(db=db) - cursor = self.conn.cursor() + self.cursor = self.conn.cursor() try: - self.database_schema = self.load_dbschema(cursor) + self.database_schema = self.load_dbschema() except sqlite.DatabaseError, error: if str(error) != 'no such table: schema': raise self.database_schema = {} - cursor = self.conn.cursor() - cursor.execute('create table schema (schema varchar)') - cursor.execute('create table ids (name varchar, num integer)') + self.cursor.execute('create table schema (schema varchar)') + self.cursor.execute('create table ids (name varchar, num integer)') + + def close(self): + ''' Close off the connection. + + Squash any error caused by us already having closed the + connection. + ''' + try: + self.conn.close() + except sqlite.ProgrammingError, value: + if str(value) != 'close failed - Connection is closed.': + raise + + # release the lock too + if self.lockfile is not None: + locking.release_lock(self.lockfile) + if self.lockfile is not None: + self.lockfile.close() + self.lockfile = None + + def rollback(self): + ''' Reverse all actions from the current transaction. + + Undo all the changes made since the database was opened or the + last commit() or rollback() was performed. + + Squash any error caused by us having closed the connection (and + therefore not having anything to roll back) + ''' + if __debug__: + print >>hyperdb.DEBUG, 'rollback', (self,) + + # roll back + try: + self.conn.rollback() + except sqlite.ProgrammingError, value: + if str(value) != 'rollback failed - Connection is closed.': + raise + + # roll back "other" transaction stuff + for method, args in self.transactions: + # delete temporary files + if method == self.doStoreFile: + self.rollbackStoreFile(*args) + self.transactions = [] def __repr__(self): return ''%id(self) - def sql_fetchone(self, cursor): + def sql_fetchone(self): ''' Fetch a single row. If there's nothing to fetch, return None. ''' - return cursor.fetchone() + return self.cursor.fetchone() + + def sql_fetchall(self): + ''' Fetch a single row. If there's nothing to fetch, return []. + ''' + return self.cursor.fetchall() def sql_commit(self): ''' Actually commit to the database. @@ -45,19 +102,19 @@ class Database(Database): if str(error) != 'cannot commit - no transaction is active': raise - def save_dbschema(self, cursor, schema): + def save_dbschema(self, schema): ''' Save the schema definition that the database currently implements ''' s = repr(self.database_schema) - self.sql(cursor, 'insert into schema values (%s)', (s,)) + self.sql('insert into schema values (%s)', (s,)) - def load_dbschema(self, cursor): + def load_dbschema(self): ''' Load the schema definition that the database currently implements ''' - cursor.execute('select schema from schema') - return eval(cursor.fetchone()[0]) + self.cursor.execute('select schema from schema') + return eval(self.cursor.fetchone()[0]) - def save_journal(self, cursor, classname, cols, nodeid, journaldate, + def save_journal(self, classname, cols, nodeid, journaldate, journaltag, action, params): ''' Save the journal entry to the database ''' @@ -71,9 +128,9 @@ class Database(Database): cols, a, a, a, a, a) if __debug__: print >>hyperdb.DEBUG, 'addjournal', (self, sql, entry) - cursor.execute(sql, entry) + self.cursor.execute(sql, entry) - def load_journal(self, cursor, classname, cols, nodeid): + def load_journal(self, classname, cols, nodeid): ''' Load the journal from the database ''' # now get the journal entries @@ -81,9 +138,9 @@ class Database(Database): self.arg) if __debug__: print >>hyperdb.DEBUG, 'getjournal', (self, sql, nodeid) - cursor.execute(sql, (nodeid,)) + self.cursor.execute(sql, (nodeid,)) res = [] - for nodeid, date_stamp, user, action, params in cursor.fetchall(): + for nodeid, date_stamp, user, action, params in self.cursor.fetchall(): params = eval(params) res.append((nodeid, date.Date(date_stamp), user, action, params)) return res @@ -112,7 +169,7 @@ class Database(Database): d[k] = date.Date(v) elif isinstance(prop, Interval) and v is not None: d[k] = date.Interval(v) - elif isinstance(prop, Password): + elif isinstance(prop, Password) and v is not None: p = password.Password() p.unpack(v) d[k] = p @@ -128,80 +185,3 @@ class Database(Database): d[k] = v return d -class Class(Class): - _marker = [] - def get(self, nodeid, propname, default=_marker, cache=1): - '''Get the value of a property on an existing node of this class. - - 'nodeid' must be the id of an existing node of this class or an - IndexError is raised. 'propname' must be the name of a property - of this class or a KeyError is raised. - - 'cache' indicates whether the transaction cache should be queried - for the node. If the node has been modified and you need to - determine what its values prior to modification are, you need to - set cache=0. - ''' - if propname == 'id': - return nodeid - - if propname == 'creation': - if not self.do_journal: - raise ValueError, 'Journalling is disabled for this class' - journal = self.db.getjournal(self.classname, nodeid) - if journal: - return self.db.getjournal(self.classname, nodeid)[0][1] - else: - # on the strange chance that there's no journal - return date.Date() - if propname == 'activity': - if not self.do_journal: - raise ValueError, 'Journalling is disabled for this class' - journal = self.db.getjournal(self.classname, nodeid) - if journal: - return self.db.getjournal(self.classname, nodeid)[-1][1] - else: - # on the strange chance that there's no journal - return date.Date() - if propname == 'creator': - if not self.do_journal: - raise ValueError, 'Journalling is disabled for this class' - journal = self.db.getjournal(self.classname, nodeid) - if journal: - name = self.db.getjournal(self.classname, nodeid)[0][2] - else: - return None - try: - return self.db.user.lookup(name) - except KeyError: - # the journaltag user doesn't exist any more - return None - - # get the property (raises KeyErorr if invalid) - prop = self.properties[propname] - - # get the node's dict - d = self.db.getnode(self.classname, nodeid) #, cache=cache) - - if not d.has_key(propname): - if default is self._marker: - if isinstance(prop, Multilink): - return [] - else: - return None - else: - return default - - # special handling for some types - if isinstance(prop, Multilink): - # don't pass our list to other code - return d[propname][:] - elif d[propname] is None: - # always return None right now, no conversion - return None - elif isinstance(prop, Boolean) or isinstance(prop, Number): - # turn Booleans and Numbers into integers - return int(d[propname]) - - return d[propname] -