diff roundup/backends/rdbms_common.py @ 1174:8e318dfaf479

Verify contents of tracker module when the tracker is opened Performance improvements in *dbm and sq backends New benchmark module. To use: PYTHONPATH=. python2 test/benchmark.py (yes, it's a little basic at present ;)
author Richard Jones <richard@users.sourceforge.net>
date Fri, 20 Sep 2002 01:20:32 +0000
parents 58f1a2c174ed
children 762f48bfbc0b
line wrap: on
line diff
--- a/roundup/backends/rdbms_common.py	Thu Sep 19 05:30:25 2002 +0000
+++ b/roundup/backends/rdbms_common.py	Fri Sep 20 01:20:32 2002 +0000
@@ -1,4 +1,4 @@
-# $Id: rdbms_common.py,v 1.6 2002-09-19 05:30:25 richard Exp $
+# $Id: rdbms_common.py,v 1.7 2002-09-20 01:20:32 richard Exp $
 
 # standard python modules
 import sys, os, time, re, errno, weakref, copy
@@ -23,9 +23,6 @@
           the sql_* methods that are NotImplemented
         - we keep a cache of the latest ROW_CACHE_SIZE row fetches.
     '''
-    # flag to set on retired entries
-    RETIRED_FLAG = '__hyperdb_retired'
-
     def __init__(self, config, journaltag=None):
         ''' Open the database and load the schema from it.
         '''
@@ -130,7 +127,7 @@
             "properties" is a list of (name, prop) where prop may be an
             instance of a hyperdb "type" _or_ a string repr of that type.
         '''
-        cols = []
+        cols = ['_activity', '_creator', '_creation']
         mls = []
         # add the multilinks separately
         for col, prop in properties:
@@ -461,6 +458,11 @@
         cl = self.classes[classname]
         cols, mls = self.determine_columns(cl.properties.items())
 
+        # add the special props
+        node = node.copy()
+        node['creation'] = node['activity'] = date.Date()
+        node['creator'] = self.journaltag
+
         # default the non-multilink columns
         for col, prop in cl.properties.items():
             if not isinstance(col, Multilink):
@@ -499,11 +501,11 @@
         # make sure we do the commit-time extra stuff for this node
         self.transactions.append((self.doSaveNode, (classname, nodeid, node)))
 
-    def setnode(self, classname, nodeid, node, multilink_changes):
+    def setnode(self, classname, nodeid, values, multilink_changes):
         ''' Change the specified node.
         '''
         if __debug__:
-            print >>hyperdb.DEBUG, 'setnode', (self, classname, nodeid, node)
+            print >>hyperdb.DEBUG, 'setnode', (self, classname, nodeid, values)
 
         # clear this node out of the cache if it's in there
         key = (classname, nodeid)
@@ -511,31 +513,40 @@
             del self.cache[key]
             self.cache_lru.remove(key)
 
-        node = self.serialise(classname, node)
+        # add the special props
+        values = values.copy()
+        values['activity'] = date.Date()
+
+        # make db-friendly
+        values = self.serialise(classname, values)
 
         cl = self.classes[classname]
         cols = []
         mls = []
         # add the multilinks separately
-        for col in node.keys():
-            prop = cl.properties[col]
+        props = cl.getprops()
+        for col in values.keys():
+            prop = props[col]
             if isinstance(prop, Multilink):
                 mls.append(col)
             else:
                 cols.append('_'+col)
         cols.sort()
 
-        # make sure the ordering is correct for column name -> column value
-        vals = tuple([node[col[1:]] for col in cols])
-        s = ','.join(['%s=%s'%(x, self.arg) for x in cols])
-        cols = ','.join(cols)
+        cursor = self.conn.cursor()
 
-        # perform the update
-        cursor = self.conn.cursor()
-        sql = 'update _%s set %s'%(classname, s)
-        if __debug__:
-            print >>hyperdb.DEBUG, 'setnode', (self, sql, vals)
-        cursor.execute(sql, vals)
+        # if there's any updates to regular columns, do them
+        if cols:
+            # make sure the ordering is correct for column name -> column value
+            sqlvals = tuple([values[col[1:]] for col in cols]) + (nodeid,)
+            s = ','.join(['%s=%s'%(x, self.arg) for x in cols])
+            cols = ','.join(cols)
+
+            # perform the update
+            sql = 'update _%s set %s where id=%s'%(classname, s, self.arg)
+            if __debug__:
+                print >>hyperdb.DEBUG, 'setnode', (self, sql, sqlvals)
+            cursor.execute(sql, sqlvals)
 
         # now the fun bit, updating the multilinks ;)
         for col, (add, remove) in multilink_changes.items():
@@ -552,7 +563,7 @@
                     self.sql(cursor, sql, (nodeid, removeid))
 
         # make sure we do the commit-time extra stuff for this node
-        self.transactions.append((self.doSaveNode, (classname, nodeid, node)))
+        self.transactions.append((self.doSaveNode, (classname, nodeid, values)))
 
     def getnode(self, classname, nodeid):
         ''' Get a node from the database.
@@ -603,9 +614,9 @@
         # save off in the cache
         key = (classname, nodeid)
         self.cache[key] = node
-	# update the LRU
-	self.cache_lru.insert(0, key)
-	del self.cache[self.cache_lru.pop()]
+        # update the LRU
+        self.cache_lru.insert(0, key)
+        del self.cache[self.cache_lru.pop()]
 
         return node
 
@@ -1171,44 +1182,28 @@
         if propname == 'id':
             return nodeid
 
+        # get the node's dict
+        d = self.db.getnode(self.classname, 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]
+            if d.has_key('creation'):
+                return d['creation']
             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]
+            if d.has_key('activity'):
+                return d['activity']
             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]
+            if d.has_key('creator'):
+                return d['creator']
             else:
-                return None
-            try:
-                return self.db.user.lookup(name)
-            except KeyError:
-                # the journaltag user doesn't exist any more
-                return None
+                return self.db.journaltag
 
         # 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):
@@ -1298,7 +1293,11 @@
             # this will raise the KeyError if the property isn't valid
             # ... we don't use getprops() here because we only care about
             # the writeable properties.
-            prop = self.properties[propname]
+            try:
+                prop = self.properties[propname]
+            except KeyError:
+                raise KeyError, '"%s" has no property named "%s"'%(
+                    self.classname, propname)
 
             # if the value's the same as the existing value, no sense in
             # doing anything
@@ -1431,14 +1430,12 @@
                 except ValueError:
                     raise TypeError, 'new property "%s" not boolean'%propname
 
-            node[propname] = value
-
         # nothing to do?
         if not propvalues:
             return propvalues
 
         # do the set, and journal it
-        self.db.setnode(self.classname, nodeid, node, multilink_changes)
+        self.db.setnode(self.classname, nodeid, propvalues, multilink_changes)
 
         if self.do_journal:
             propvalues.update(journalvalues)
@@ -1575,16 +1572,15 @@
             raise TypeError, 'No key property set for class %s'%self.classname
 
         cursor = self.db.conn.cursor()
-        sql = 'select id from _%s where _%s=%s'%(self.classname, self.key,
-            self.db.arg)
-        if __debug__:
-            print >>hyperdb.DEBUG, 'lookup', (self, sql, keyvalue)
-        cursor.execute(sql, (keyvalue,))
+        sql = 'select id,__retired__ from _%s where _%s=%s'%(self.classname,
+            self.key, self.db.arg)
+        self.db.sql(cursor, sql, (keyvalue,))
 
-        # see if there was a result
+        # see if there was a result that's not retired
         l = cursor.fetchall()
-        if not l:
-            raise KeyError, keyvalue
+        if not l or int(l[0][1]):
+            raise KeyError, 'No key (%s) value "%s" for "%s"'%(self.key,
+                keyvalue, self.classname)
 
         # return the id
         return l[0][0]
@@ -1665,7 +1661,7 @@
                 tn = '%s_%s'%(cn, k)
                 frum.append(tn)
                 if isinstance(v, type([])):
-                    s = ','.join([self.arg for x in v])
+                    s = ','.join([a for x in v])
                     where.append('id=%s.nodeid and %s.linkid in (%s)'%(tn,tn,s))
                     args = args + v
                 else:
@@ -1733,27 +1729,13 @@
         if sort[0] is not None and sort[1] is not None:
             direction, colname = sort
             if direction != '-':
-                if colname == 'activity':
-                    orderby.append('activity')
-                    ordercols.append('max(%s__journal.date) as activity'%cn)
-                    frum.append('%s__journal'%cn)
-                    where.append('%s__journal.nodeid = _%s.id'%(cn, cn))
-                    # we need to group by id
-                    group = ' group by id'
-                elif colname == 'id':
+                if colname == 'id':
                     orderby.append(colname)
                 else:
                     orderby.append('_'+colname)
                     ordercols.append('_'+colname)
             else:
-                if colname == 'activity':
-                    orderby.append('activity desc')
-                    ordercols.append('max(%s__journal.date) as activity'%cn)
-                    frum.append('%s__journal'%cn)
-                    where.append('%s__journal.nodeid = _%s.id'%(cn, cn))
-                    # we need to group by id
-                    group = ' group by id'
-                elif colname == 'id':
+                if colname == 'id':
                     orderby.append(colname+' desc')
                     ordercols.append(colname)
                 else:

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