Code

Fixed a backlog of bug reports, and worked on python 2.3 compatibility:
[roundup.git] / roundup / backends / rdbms_common.py
index cd24b8430dbf42144b428841247afb4832f5e3c9..002f5a721fceaac5f8901343d8bca066fa6873e6 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: rdbms_common.py,v 1.23 2002-10-31 04:02:23 richard Exp $
+# $Id: rdbms_common.py,v 1.30 2003-02-06 05:43:47 richard Exp $
 ''' Relational database (SQL) backend common code.
 
 Basics:
@@ -28,6 +28,7 @@ import sys, os, time, re, errno, weakref, copy
 from roundup import hyperdb, date, password, roundupdb, security
 from roundup.hyperdb import String, Password, Date, Interval, Link, \
     Multilink, DatabaseError, Boolean, Number
+from roundup.backends import locking
 
 # support
 from blobfiles import FileStorage
@@ -62,6 +63,9 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database):
         self.cache = {}
         self.cache_lru = []
 
+        # database lock
+        self.lockfile = None
+
         # open a connection to the database, creating the "conn" attribute
         self.open_connection()
 
@@ -903,6 +907,11 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database):
         ''' Close off the connection.
         '''
         self.conn.close()
+        if self.lockfile is not None:
+            locking.release_lock(self.lockfile)
+        if self.lockfile is not None:
+            self.lockfile.close()
+            self.lockfile = None
 
 #
 # The base Class class
@@ -1061,7 +1070,7 @@ class Class(hyperdb.Class):
                             (self.classname, newid, key))
 
             elif isinstance(prop, String):
-                if type(value) != type(''):
+                if type(value) != type('') and type(value) != type(u''):
                     raise TypeError, 'new property "%s" not a string'%key
 
             elif isinstance(prop, Password):
@@ -1102,7 +1111,7 @@ class Class(hyperdb.Class):
         # done
         self.db.addnode(self.classname, newid, propvalues)
         if self.do_journal:
-            self.db.addjournal(self.classname, newid, 'create', propvalues)
+            self.db.addjournal(self.classname, newid, 'create', {})
 
         self.fireReactors('create', newid, None)
 
@@ -1184,7 +1193,7 @@ class Class(hyperdb.Class):
             creation = None
         if d.has_key('activity'):
             del d['activity']
-        self.db.addjournal(self.classname, newid, 'create', d, creator,
+        self.db.addjournal(self.classname, newid, 'create', {}, creator,
             creation)
         return newid
 
@@ -1323,9 +1332,11 @@ class Class(hyperdb.Class):
 
             # if the value's the same as the existing value, no sense in
             # doing anything
-            if node.has_key(propname) and value == node[propname]:
+            current = node.get(propname, None)
+            if value == current:
                 del propvalues[propname]
                 continue
+            journalvalues[propname] = current
 
             # do stuff based on the prop type
             if isinstance(prop, Link):
@@ -1421,7 +1432,7 @@ class Class(hyperdb.Class):
                     journalvalues[propname] = tuple(l)
 
             elif isinstance(prop, String):
-                if value is not None and type(value) != type(''):
+                if value is not None and type(value) != type('') and type(value) != type(u''):
                     raise TypeError, 'new property "%s" not a string'%propname
 
             elif isinstance(prop, Password):
@@ -1460,8 +1471,7 @@ class Class(hyperdb.Class):
         self.db.setnode(self.classname, nodeid, propvalues, multilink_changes)
 
         if self.do_journal:
-            propvalues.update(journalvalues)
-            self.db.addjournal(self.classname, nodeid, 'set', propvalues)
+            self.db.addjournal(self.classname, nodeid, 'set', journalvalues)
 
         self.fireReactors('set', nodeid, oldvalues)
 
@@ -1479,6 +1489,8 @@ class Class(hyperdb.Class):
         if self.db.journaltag is None:
             raise DatabaseError, 'Database open read-only'
 
+        self.fireAuditors('retire', nodeid, None)
+
         # use the arg for __retired__ to cope with any odd database type
         # conversion (hello, sqlite)
         sql = 'update _%s set __retired__=%s where id=%s'%(self.classname,
@@ -1487,6 +1499,8 @@ class Class(hyperdb.Class):
             print >>hyperdb.DEBUG, 'retire', (self, sql, nodeid)
         self.db.cursor.execute(sql, (1, nodeid))
 
+        self.fireReactors('retire', nodeid, None)
+
     def is_retired(self, nodeid):
         '''Return true if the node is rerired
         '''
@@ -1526,7 +1540,7 @@ class Class(hyperdb.Class):
 
         The returned list contains tuples of the form
 
-            (date, tag, action, params)
+            (nodeid, date, tag, action, params)
 
         'date' is a Timestamp object specifying the time of the change and
         'tag' is the journaltag specified when the database was opened.
@@ -1748,6 +1762,14 @@ class Class(hyperdb.Class):
                 else:
                     where.append('id=%s.nodeid and %s.linkid = %s'%(tn, tn, a))
                     args.append(v)
+            elif k == 'id':
+                if isinstance(v, type([])):
+                    s = ','.join([a for x in v])
+                    where.append('%s in (%s)'%(k, s))
+                    args = args + v
+                else:
+                    where.append('%s=%s'%(k, a))
+                    args.append(v)
             elif isinstance(propclass, String):
                 if not isinstance(v, type([])):
                     v = [v]
@@ -1780,6 +1802,22 @@ class Class(hyperdb.Class):
                     else:
                         where.append('_%s=%s'%(k, a))
                         args.append(v)
+            elif isinstance(propclass, Date):
+                if isinstance(v, type([])):
+                    s = ','.join([a for x in v])
+                    where.append('_%s in (%s)'%(k, s))
+                    args = args + [date.Date(x).serialise() for x in v]
+                else:
+                    where.append('_%s=%s'%(k, a))
+                    args.append(date.Date(v).serialise())
+            elif isinstance(propclass, Interval):
+                if isinstance(v, type([])):
+                    s = ','.join([a for x in v])
+                    where.append('_%s in (%s)'%(k, s))
+                    args = args + [date.Interval(x).serialise() for x in v]
+                else:
+                    where.append('_%s=%s'%(k, a))
+                    args.append(date.Interval(v).serialise())
             else:
                 if isinstance(v, type([])):
                     s = ','.join([a for x in v])