Code

use the upload-supplied content-type if there is one
[roundup.git] / roundup / backends / back_mysql.py
index fa3c6d4ccb97f50d947083bd5159e05066885105..7ead40200d1ca568ead60ad320728171f6593339 100644 (file)
@@ -411,6 +411,92 @@ class MysqlClass:
         # 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):