summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 6216db0)
raw | patch | inline | side by side (parent: 6216db0)
author | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Tue, 20 Jan 2004 03:58:38 +0000 (03:58 +0000) | ||
committer | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Tue, 20 Jan 2004 03:58:38 +0000 (03:58 +0000) |
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@2054 57a73879-2fb5-44c3-a270-3262357dd7e2
diff --git a/CHANGES.txt b/CHANGES.txt
index 7a9743f1075fd0465cedef3fb18312f839056e4d..a4a6dea0644565ce5ecc3c2091cba7f43f9a6ce1 100644 (file)
--- a/CHANGES.txt
+++ b/CHANGES.txt
- the mail gateway now searches recursively for the text/plain and the
attachments of a message (sf bug 841241).
- fixed display of feedback messages in some situations (sf bug 739545)
+- use supplied content-type on file uploads before trying filename)
Cleanup:
- replace curuserid attribute on Database with the extended getuid() method.
diff --git a/TODO.txt b/TODO.txt
index 2da8880aa62317170ca43a2e38cd46c3823db3d9..cf79d7fedd3d13c057d9ec1aa5fbd9f6cebf3187 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
This file has been re-purposed to contain specifically the items that need
doing before the next release:
+- add tests for group-by-multilink so I finally implement it for the RDBMSes
- full coverage analysis for unit tests
- migrate to numeric ID values (fixes bug 817217)
index fa3c6d4ccb97f50d947083bd5159e05066885105..7ead40200d1ca568ead60ad320728171f6593339 100644 (file)
# return the IDs (the first column)
return [row[0] for row in l]
+ # mysql doesn't implement INTERSECT
+ def find(self, **propspec):
+ '''Get the ids of nodes in this class which link to the given nodes.
+
+ 'propspec' consists of keyword args propname=nodeid or
+ propname={nodeid:1, }
+ 'propname' must be the name of a property in this class, or a
+ KeyError is raised. That property must be a Link or
+ Multilink property, or a TypeError is raised.
+
+ Any node in this class whose 'propname' property links to any of the
+ nodeids will be returned. Used by the full text indexing, which knows
+ that "foo" occurs in msg1, msg3 and file7, so we have hits on these
+ issues:
+
+ db.issue.find(messages={'1':1,'3':1}, files={'7':1})
+ '''
+ if __debug__:
+ print >>hyperdb.DEBUG, 'find', (self, propspec)
+
+ # shortcut
+ if not propspec:
+ return []
+
+ # validate the args
+ props = self.getprops()
+ propspec = propspec.items()
+ for propname, nodeids in propspec:
+ # check the prop is OK
+ prop = props[propname]
+ if not isinstance(prop, Link) and not isinstance(prop, Multilink):
+ raise TypeError, "'%s' not a Link/Multilink property"%propname
+
+ # first, links
+ a = self.db.arg
+ where = ['__retired__ <> %s'%a]
+ allvalues = (1,)
+ for prop, values in propspec:
+ if not isinstance(props[prop], hyperdb.Link):
+ continue
+ if type(values) is type({}) and len(values) == 1:
+ values = values.keys()[0]
+ if type(values) is type(''):
+ allvalues += (values,)
+ where.append('_%s = %s'%(prop, a))
+ elif values is None:
+ where.append('_%s is NULL'%prop)
+ else:
+ allvalues += tuple(values.keys())
+ where.append('_%s in (%s)'%(prop, ','.join([a]*len(values))))
+ tables = []
+ if where:
+ tables.append('select id as nodeid from _%s where %s'%(
+ self.classname, ' and '.join(where)))
+
+ # now multilinks
+ for prop, values in propspec:
+ if not isinstance(props[prop], hyperdb.Multilink):
+ continue
+ if type(values) is type(''):
+ allvalues += (values,)
+ s = a
+ else:
+ allvalues += tuple(values.keys())
+ s = ','.join([a]*len(values))
+ tables.append('select nodeid from %s_%s where linkid in (%s)'%(
+ self.classname, prop, s))
+
+ raise NotImplemented, "XXX this code's farked"
+ d = {}
+ self.db.sql(sql, allvalues)
+ for result in self.db.sql_fetchall():
+ d[result[0]] = 1
+
+ for query in tables[1:]:
+ self.db.sql(sql, allvalues)
+ for result in self.db.sql_fetchall():
+ if not d.has_key(result[0]):
+ continue
+
+ if __debug__:
+ print >>hyperdb.DEBUG, 'find ... ', l
+ l = d.keys()
+ l.sort()
+ return l
+
class Class(MysqlClass, rdbms_common.Class):
pass
class IssueClass(MysqlClass, rdbms_common.IssueClass):
index 45078c44b0f3237e3bdcf31e4c4c89fdbcf53f94..d9e2d582b349ce80246c6fabf125a0caa81c3358 100644 (file)
-# $Id: rdbms_common.py,v 1.72 2003-12-05 09:47:46 richard Exp $
+# $Id: rdbms_common.py,v 1.73 2004-01-20 03:58:38 richard Exp $
''' Relational database (SQL) backend common code.
Basics:
raise TypeError, "'%s' not a Link/Multilink property"%propname
# first, links
- where = ['__retired__ = %s']
- allvalues = (0,)
a = self.db.arg
+ where = ['__retired__ <> %s'%a]
+ allvalues = (1,)
for prop, values in propspec:
if not isinstance(props[prop], hyperdb.Link):
continue
s = ','.join([a]*len(values))
tables.append('select nodeid from %s_%s where linkid in (%s)'%(
self.classname, prop, s))
- sql = '\nunion\n'.join(tables)
+
+ sql = '\nintersect\n'.join(tables)
self.db.sql(sql, allvalues)
l = [x[0] for x in self.db.sql_fetchall()]
if __debug__:
diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py
index 372100284369582e2cd7398054f5f2d00ec35276..b53a38cd8c6d812643817ea2295eb0eec19a4a2b 100644 (file)
--- a/roundup/cgi/client.py
+++ b/roundup/cgi/client.py
-# $Id: client.py,v 1.152 2004-01-19 23:56:07 richard Exp $
+# $Id: client.py,v 1.153 2004-01-20 03:58:38 richard Exp $
__doc__ = """
WWW request handler (also used in the stand-alone server).
props['name'] = fn
# use this info as the type/filename properties
if propdef.has_key('type'):
- props['type'] = mimetypes.guess_type(fn)[0]
- if not props['type']:
+ if hasattr(value, 'type'):
+ props['type'] = value.type
+ elif mimetypes.guess_type(fn)[0]:
+ props['type'] = mimetypes.guess_type(fn)[0]
+ else:
props['type'] = "application/octet-stream"
# finally, read the content RAW
value = value.value
diff --git a/roundup/indexer.py b/roundup/indexer.py
index ef697d938f968bb475c57026124f45ad64fdfcfd..9bee8bd19e19b54d5ddb4495ae522be4302a11e7 100644 (file)
--- a/roundup/indexer.py
+++ b/roundup/indexer.py
# that promote freedom, but obviously am giving up any rights
# to compel such.
#
-#$Id: indexer.py,v 1.16 2003-01-14 03:56:44 richard Exp $
+#$Id: indexer.py,v 1.17 2004-01-20 03:58:38 richard Exp $
'''
This module provides an indexer class, RoundupIndexer, that stores text
indices in a roundup instance. This class makes searching the content of
if not hits:
return {}
- #designator_propname = {'msg': 'messages', 'file': 'files'}
designator_propname = {}
for nm, propclass in klass.getprops().items():
if isinstance(propclass, Link) or isinstance(propclass, Multilink):
# build a dictionary of nodes and their associated messages
# and files
- nodeids = {} # this is the answer
+ nodeids = {} # this is the answer
propspec = {} # used to do the klass.find
for propname in designator_propname.values():
propspec[propname] = {} # used as a set (value doesn't matter)
diff --git a/test/db_test_base.py b/test/db_test_base.py
index ed707abb1cc7c49915bd391acfabb1be7ef1e1ac..9945ef4ded0568b2f9312f56af28bc7c529324d5 100644 (file)
--- a/test/db_test_base.py
+++ b/test/db_test_base.py
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: db_test_base.py,v 1.12 2003-12-10 01:40:51 richard Exp $
+# $Id: db_test_base.py,v 1.13 2004-01-20 03:58:38 richard Exp $
import unittest, os, shutil, errno, imp, sys, time, pprint
# we should have the create and last set entries now
self.assertEqual(jlen-1, len(self.db.getjournal('issue', id)))
- def testSearching(self):
- self.db.file.create(content='hello', type="text/plain")
- self.db.file.create(content='world', type="text/frozz",
+ def testIndexerSearching(self):
+ f1 = self.db.file.create(content='hello', type="text/plain")
+ f2 = self.db.file.create(content='world', type="text/frozz",
comment='blah blah')
- self.db.issue.create(files=['1', '2'], title="flebble plop")
- self.db.issue.create(title="flebble frooz")
+ i1 = self.db.issue.create(files=[f1, f2], title="flebble plop")
+ i2 = self.db.issue.create(title="flebble frooz")
self.db.commit()
self.assertEquals(self.db.indexer.search(['hello'], self.db.issue),
- {'1': {'files': ['1']}})
+ {i1: {'files': [f1]}})
self.assertEquals(self.db.indexer.search(['world'], self.db.issue), {})
self.assertEquals(self.db.indexer.search(['frooz'], self.db.issue),
- {'2': {}})
+ {i2: {}})
self.assertEquals(self.db.indexer.search(['flebble'], self.db.issue),
- {'2': {}, '1': {}})
+ {i1: {}, i2: {}})
def testReindexing(self):
self.db.issue.create(title="frooz")