Code

- fixed rdbms searching by ID (sf bug 666615)
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Sun, 12 Jan 2003 23:53:20 +0000 (23:53 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Sun, 12 Jan 2003 23:53:20 +0000 (23:53 +0000)
- detect corrupted index and raise semi-useful exception (sf bug 666767)

also some mysql support (in tests)

git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1441 57a73879-2fb5-44c3-a270-3262357dd7e2

CHANGES.txt
TODO.txt
doc/customizing.txt
roundup/backends/__init__.py
roundup/backends/back_gadfly.py
roundup/backends/rdbms_common.py
roundup/indexer.py
test/test_db.py

index 43ae26017fdccedb113d58e5e3f11e3a04599535..d36285075ccd565ea0f28b9e693215a5cdb2ba4b 100644 (file)
@@ -11,6 +11,11 @@ are given with the most recent entry first.
 - applied patch for nicer history display (sf feature 638280)
 
 
+2003-??-?? 0.5.5
+- fixed rdbms searching by ID (sf bug 666615)
+- detect corrupted index and raise semi-useful exception (sf bug 666767)
+
+
 2003-01-10 0.5.4
 - key the templates cache off full path, not filename
 - implemented whole-database locking
index 8947322fe6142b53c93cce5af1e47f0d43cfbbcf..d73253626433120b95e2d12c6d4758176a29532c 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
@@ -58,5 +58,7 @@ pending web       multilink item removal action with retirement
 pending web       implement a python dict version of the form values
 pending web       implement the request.url attribute?
 pending web       UNIX init.d script for roundup-server
+
+bug     hyperdb   need unit tests for firing of auditors and reactors
 ======= ========= =============================================================
 
index 3ff2f48f3affc45ba2578289d1d376701d850942..122b87223635527cf3414295ba5a857db77aa391 100644 (file)
@@ -2,7 +2,7 @@
 Customising Roundup
 ===================
 
-:Version: $Revision: 1.69 $
+:Version: $Revision: 1.70 $
 
 .. This document borrows from the ZopeBook section on ZPT. The original is at:
    http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx
@@ -999,7 +999,7 @@ forms:
    in place if the "foo" form variable doesn't exist.
 
 **String Expressions** - eg. ``string:hello ${user/name}``
-   These expressions are simple string interpolations (though they can be just
+   These expressions are simple string interpolations though they can be just
    plain strings with no interpolation if you want. The expression in the
    ``${ ... }`` is just a path expression as above.
 
index 047c29452e43d15d645900e952414a070fb2b7b4..7dfe3e8eebfbe063e3bd036a8857cf5858a43183 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: __init__.py,v 1.20 2002-10-07 00:52:51 richard Exp $
+# $Id: __init__.py,v 1.21 2003-01-12 23:53:19 richard Exp $
 
 ''' Container for the hyperdb storage backend implementations.
 
@@ -56,6 +56,15 @@ else:
     gadfly = back_gadfly
     __all__.append('gadfly')
 
+try:
+    import MySQLdb
+except ImportError, message:
+    if str(message) != 'No module named MySQLdb': raise
+else:
+    import back_mysql
+    mysql = back_mysql
+    __all__.append('mysql')
+
 try:
     import sqlite
 except ImportError, message:
index da9347731813ab23fc9785ae768e3a6d2d0a8d6c..f4661dbe58f434c3558d28c3d52929320da10618 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: back_gadfly.py,v 1.31 2003-01-08 05:39:40 richard Exp $
+# $Id: back_gadfly.py,v 1.32 2003-01-12 23:53:20 richard Exp $
 ''' Gadlfy relational database hypderb backend.
 
 About Gadfly
@@ -185,6 +185,14 @@ class GadflyClass:
                 else:
                     where.append('_%s=%s'%(k, a))
                     args.append(date.Interval(v).serialise())
+            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)
             else:
                 if isinstance(v, type([])):
                     s = ','.join([a for x in v])
index 9df7a3e201c3d8d1053c550f133aeb953aa714dc..550b51b7024d9b97846274dcce4ce8ac9d44d5ab 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: rdbms_common.py,v 1.27 2003-01-08 05:39:40 richard Exp $
+# $Id: rdbms_common.py,v 1.28 2003-01-12 23:53:20 richard Exp $
 ''' Relational database (SQL) backend common code.
 
 Basics:
@@ -1762,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]
index e4d1d59b02c186e522b9b3addc707bd52ffe7c6a..4c8b913e273eaab43a2d85bbd48a2dbbb9e3a044 100644 (file)
@@ -14,7 +14,7 @@
 #     that promote freedom, but obviously am giving up any rights
 #     to compel such.
 # 
-#$Id: indexer.py,v 1.14 2002-09-25 05:06:14 richard Exp $
+#$Id: indexer.py,v 1.15 2003-01-12 23:53:19 richard Exp $
 '''
 This module provides an indexer class, RoundupIndexer, that stores text
 indices in a roundup instance.  This class makes searching the content of
@@ -214,13 +214,15 @@ class Indexer:
                 # word outside the bounds of what we index - ignore
                 continue
             word = word.upper()
-            entry = self.words.get(word)    # For each word, get index
-            entries[word] = entry           #   of matching files
-            if not entry:                   # Nothing for this one word (fail)
+            entry = self.words[word]    # For each word, get index
+            entries[word] = entry       #   of matching files
+            if not entry:               # Nothing for this one word (fail)
                 return {}
             if hits is None:
                 hits = {}
                 for k in entry.keys():
+                    if not self.fileids.has_key(k):
+                        raise ValueError, 'Index is corrupted: re-generate it'
                     hits[k] = self.fileids[k]
             else:
                 # Eliminate hits for every non-match
index 089f8de60c9bc5e47175ddd4d7e33fecce8040c4..d44d23648daa19512a9f8e4b4d861d37fdf0713b 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: test_db.py,v 1.64 2003-01-12 00:43:43 richard Exp $ 
+# $Id: test_db.py,v 1.65 2003-01-12 23:53:20 richard Exp $ 
 
 import unittest, os, shutil, time
 
@@ -570,6 +570,10 @@ class anydbmDBTestCase(MyTestCase):
         self.db.commit()
         return self.assertEqual, self.db.issue.filter
 
+    def testFilteringID(self):
+        ae, filt = self.filteringSetup()
+        ae(filt(None, {'id': '1'}, ('+','id'), (None,None)), ['1'])
+
     def testFilteringString(self):
         ae, filt = self.filteringSetup()
         ae(filt(None, {'title': 'issue one'}, ('+','id'), (None,None)), ['1'])
@@ -698,6 +702,32 @@ class gadflyReadOnlyDBTestCase(anydbmReadOnlyDBTestCase):
         setupSchema(self.db, 0, gadfly)
 
 
+class mysqlDBTestCase(anydbmDBTestCase):
+    def setUp(self):
+        from roundup.backends import mysql
+        # remove previous test, ignore errors
+        if os.path.exists(config.DATABASE):
+            shutil.rmtree(config.DATABASE)
+        config.MYSQL_DATABASE='mysql@localhost root rootpasswd'.split()
+        os.makedirs(config.DATABASE + '/files')
+        self.db = mysql.Database(config, 'admin')
+        setupSchema(self.db, 1, mysql)
+
+class mysqlReadOnlyDBTestCase(anydbmReadOnlyDBTestCase):
+    def setUp(self):
+        from roundup.backends import mysql
+        # remove previous test, ignore errors
+        if os.path.exists(config.DATABASE):
+            shutil.rmtree(config.DATABASE)
+        config.MYSQL_DATABASE='mysql@localhost root rootpasswd'.split()
+        os.makedirs(config.DATABASE + '/files')
+        db = mysql.Database(config, 'admin')
+        setupSchema(db, 1, mysql)
+        db.close()
+        self.db = sqlite.Database(config)
+        setupSchema(self.db, 0, mysql)
+
+
 class sqliteDBTestCase(anydbmDBTestCase):
     def setUp(self):
         from roundup.backends import sqlite
@@ -708,9 +738,6 @@ class sqliteDBTestCase(anydbmDBTestCase):
         self.db = sqlite.Database(config, 'admin')
         setupSchema(self.db, 1, sqlite)
 
-    def testIDGeneration(self):
-        pass
-
 class sqliteReadOnlyDBTestCase(anydbmReadOnlyDBTestCase):
     def setUp(self):
         from roundup.backends import sqlite
@@ -791,6 +818,11 @@ def suite():
 #    return unittest.TestSuite(l)
 
     from roundup import backends
+#    if hasattr(backends, 'mysql'):
+#        l.append(unittest.makeSuite(mysqlDBTestCase, 'test'))
+#        l.append(unittest.makeSuite(mysqlReadOnlyDBTestCase, 'test'))
+#    return unittest.TestSuite(l)
+
     if hasattr(backends, 'gadfly'):
         l.append(unittest.makeSuite(gadflyDBTestCase, 'test'))
         l.append(unittest.makeSuite(gadflyReadOnlyDBTestCase, 'test'))