summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 7f0d590)
raw | patch | inline | side by side (parent: 7f0d590)
author | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Wed, 18 Sep 2002 07:04:39 +0000 (07:04 +0000) | ||
committer | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Wed, 18 Sep 2002 07:04:39 +0000 (07:04 +0000) |
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1192 57a73879-2fb5-44c3-a270-3262357dd7e2
roundup/backends/back_sqlite.py | patch | blob | history | |
roundup/backends/rdbms_common.py | patch | blob | history | |
test/test_db.py | patch | blob | history |
index 7dae5df67776641c5b47b78801bbe8e6495ffa7f..6f1f3590178c00b9b00fde3fe46946dcb2790b03 100644 (file)
-# $Id: back_sqlite.py,v 1.1 2002-09-18 05:07:47 richard Exp $
+# $Id: back_sqlite.py,v 1.2 2002-09-18 07:04:37 richard Exp $
__doc__ = '''
See https://pysqlite.sourceforge.net/ for pysqlite info
'''
res.append((nodeid, date.Date(date_stamp), user, action, params))
return res
+ def unserialise(self, classname, node):
+ ''' Decode the marshalled node data
+
+ SQLite stringifies _everything_... so we need to re-numberificate
+ Booleans and Numbers.
+ '''
+ if __debug__:
+ print >>hyperdb.DEBUG, 'unserialise', classname, node
+ properties = self.getclass(classname).getprops()
+ d = {}
+ for k, v in node.items():
+ # if the property doesn't exist, or is the "retired" flag then
+ # it won't be in the properties dict
+ if not properties.has_key(k):
+ d[k] = v
+ continue
+
+ # get the property spec
+ prop = properties[k]
+
+ if isinstance(prop, Date) and v is not None:
+ d[k] = date.Date(v)
+ elif isinstance(prop, Interval) and v is not None:
+ d[k] = date.Interval(v)
+ elif isinstance(prop, Password):
+ p = password.Password()
+ p.unpack(v)
+ d[k] = p
+ elif isinstance(prop, Boolean) and v is not None:
+ d[k] = int(v)
+ elif isinstance(prop, Number) and v is not None:
+ # try int first, then assume it's a float
+ try:
+ d[k] = int(v)
+ except ValueError:
+ d[k] = float(v)
+ else:
+ 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]
+
index d264a581b8d0f0d4c4b83ca1c19c6695fcb51afd..1d1f8a3c2921c135c5eb38e3121a171f1b82efa5 100644 (file)
-# $Id: rdbms_common.py,v 1.1 2002-09-18 05:07:47 richard Exp $
+# $Id: rdbms_common.py,v 1.2 2002-09-18 07:04:38 richard Exp $
# standard python modules
import sys, os, time, re, errno, weakref, copy
attribute actually matches the schema in the database.
'''
# now detect changes in the schema
+ save = 0
for classname, spec in self.classes.items():
if self.database_schema.has_key(classname):
dbspec = self.database_schema[classname]
- self.update_class(spec, dbspec)
- self.database_schema[classname] = spec.schema()
+ if self.update_class(spec, dbspec):
+ self.database_schema[classname] = spec.schema()
+ save = 1
else:
self.create_class(spec)
self.database_schema[classname] = spec.schema()
+ save = 1
for classname in self.database_schema.keys():
if not self.classes.has_key(classname):
self.drop_class(classname)
# update the database version of the schema
- cursor = self.conn.cursor()
- self.sql(cursor, 'delete from schema')
- self.save_dbschema(cursor, self.database_schema)
+ if save:
+ cursor = self.conn.cursor()
+ self.sql(cursor, 'delete from schema')
+ self.save_dbschema(cursor, self.database_schema)
# reindex the db if necessary
if self.indexer.should_reindex():
'''
spec_schema = spec.schema()
if spec_schema == dbspec:
- return
+ # no save needed for this one
+ return 0
if __debug__:
print >>hyperdb.DEBUG, 'update_class FIRING'
qs = ','.join([self.arg for x in cols])
sql = 'insert into _%s values (%s)'%(cn, s)
cursor.execute(sql, olddata)
+ return 1
def create_class_table(self, cursor, spec):
''' create the class table for the given spec
frum = ['_'+cn]
where = []
args = []
+ a = self.db.arg
for k, v in filterspec.items():
propclass = props[k]
if isinstance(propclass, Multilink):
args.append(v)
else:
if isinstance(v, type([])):
- s = ','.join([self.arg for x in v])
+ s = ','.join([a for x in v])
where.append('_%s in (%s)'%(k, s))
args = args + v
else:
- where.append('_%s=%s'%(k, self.arg))
+ where.append('_%s=%s'%(k, a))
args.append(v)
# add results of full text search
if search_matches is not None:
v = search_matches.keys()
- s = ','.join([self.arg for x in v])
+ s = ','.join([a for x in v])
where.append('id in (%s)'%s)
args = args + v
orderby = []
ordercols = []
if sort[0] is not None and sort[1] is not None:
- if sort[0] != '-':
- orderby.append('_'+sort[1])
- ordercols.append(sort[1])
+ 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))
+ else:
+ orderby.append('_'+colname)
+ ordercols.append('_'+colname)
else:
- orderby.append('_'+sort[1]+' desc')
- ordercols.append(sort[1])
+ 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))
+ else:
+ orderby.append('_'+colname+' desc')
+ ordercols.append('_'+colname)
# figure the group by clause
groupby = []
if group[0] is not None and group[1] is not None:
if group[0] != '-':
groupby.append('_'+group[1])
- groupcols.append(group[1])
+ groupcols.append('_'+group[1])
else:
groupby.append('_'+group[1]+' desc')
- groupcols.append(group[1])
+ groupcols.append('_'+group[1])
# construct the SQL
frum = ','.join(frum)
order = ' order by %s'%(','.join(orderby))
else:
order = ''
- if groupby:
+ if 0: #groupby:
cols = cols + groupcols
group = ' group by %s'%(','.join(groupby))
else:
group)
args = tuple(args)
if __debug__:
- print >>hyperdb.DEBUG, 'find', (self, sql, args)
+ print >>hyperdb.DEBUG, 'filter', (self, sql, args)
cursor = self.db.conn.cursor()
cursor.execute(sql, args)
+ # return the IDs
+ return [row[0] for row in cursor.fetchall()]
+
def count(self):
'''Get the number of nodes in this class.
diff --git a/test/test_db.py b/test/test_db.py
index 7e84e6a3f3e9bb99a0c5b1e7994b85ff9f34e7b2..6d5cabc0cd6cbc9bafe2c7101cba30e14c5a55cc 100644 (file)
--- a/test/test_db.py
+++ b/test/test_db.py
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: test_db.py,v 1.48 2002-09-18 05:07:48 richard Exp $
+# $Id: test_db.py,v 1.49 2002-09-18 07:04:39 richard Exp $
import unittest, os, shutil, time
def testBooleanChange(self):
userid = self.db.user.create(username='foo', assignable=1)
- self.db.user.create(username='foo2', assignable=0)
- a = self.db.user.get(userid, 'assignable')
+ self.assertEqual(1, self.db.user.get(userid, 'assignable'))
self.db.user.set(userid, assignable=0)
- self.assertNotEqual(self.db.user.get(userid, 'assignable'), a)
- self.db.user.set(userid, assignable=0)
- self.db.user.set(userid, assignable=1)
- self.db.user.set('1', assignable=None)
+ self.assertEqual(self.db.user.get(userid, 'assignable'), 0)
+ self.db.user.set(userid, assignable=None)
self.assertEqual(self.db.user.get('1', "assignable"), None)
def testNumberChange(self):
- self.db.user.create(username='foo', age='1')
- a = self.db.user.get('1', 'age')
- self.db.user.set('1', age='3')
- self.assertNotEqual(self.db.user.get('1', 'age'), a)
- self.db.user.set('1', age='1.0')
+ self.db.user.create(username='foo', age=1)
+ self.assertEqual(1, self.db.user.get('1', 'age'))
+ self.db.user.set('1', age=3)
+ self.assertNotEqual(self.db.user.get('1', 'age'), 1)
+ self.db.user.set('1', age=1.0)
self.db.user.set('1', age=None)
self.assertEqual(self.db.user.get('1', "age"), None)
unittest.makeSuite(anydbmDBTestCase, 'test'),
unittest.makeSuite(anydbmReadOnlyDBTestCase, 'test')
]
- #return unittest.TestSuite(l)
+# return unittest.TestSuite(l)
try:
import bsddb