Code

hyperdb grows a refresh_database() method. There will be a future
authoranthonybaxter <anthonybaxter@57a73879-2fb5-44c3-a270-3262357dd7e2>
Tue, 7 Oct 2003 11:58:58 +0000 (11:58 +0000)
committeranthonybaxter <anthonybaxter@57a73879-2fb5-44c3-a270-3262357dd7e2>
Tue, 7 Oct 2003 11:58:58 +0000 (11:58 +0000)
roundup-admin command to invoke this.

XXXX Unit tests do _not_ cover large slabs of the hyperdb backend code,
it seems. :-(

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

roundup/backends/back_anydbm.py
roundup/backends/back_metakit.py
roundup/backends/rdbms_common.py
roundup/hyperdb.py

index 8d7ecd884e66b0110140d442c950f725f8d50ed7..8dae659eca3ce4294aa0c38831a4a180e507cafc 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-#$Id: back_anydbm.py,v 1.128 2003-09-14 18:55:37 jlgijsbers Exp $
+#$Id: back_anydbm.py,v 1.129 2003-10-07 11:58:57 anthonybaxter Exp $
 '''
 This module defines a backend that saves the hyperdatabase in a database
 chosen by anydbm. It is guaranteed to always be available in python
@@ -98,6 +98,10 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database):
         if self.indexer.should_reindex():
             self.reindex()
 
+    def refresh_database(self):
+        "Rebuild the database"
+        self.reindex()
+
     def reindex(self):
         for klass in self.classes.values():
             for nodeid in klass.list():
index 68dc2955290742b85028b52c013acafc05b885ab..737d08d3faa6883cfae26f3d8c1af95c8aa668a7 100755 (executable)
@@ -1,4 +1,4 @@
-# $Id: back_metakit.py,v 1.50 2003-09-08 20:39:18 jlgijsbers Exp $
+# $Id: back_metakit.py,v 1.51 2003-10-07 11:58:57 anthonybaxter Exp $
 '''
    Metakit backend for Roundup, originally by Gordon McMillan.
 
@@ -69,6 +69,10 @@ class _Database(hyperdb.Database, roundupdb.Database):
         if self.indexer.should_reindex():
             self.reindex()
 
+    def refresh_database(self):
+        # XXX handle refresh
+        self.reindex()
+
     def reindex(self):
         for klass in self.classes.values():
             for nodeid in klass.list():
index b88b2e2b10df2de6da30a1630a16d02a3754f34f..00921016ff1c185a6e67cd47970b7dc2b2e370ef 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: rdbms_common.py,v 1.64 2003-10-07 08:34:58 anthonybaxter Exp $
+# $Id: rdbms_common.py,v 1.65 2003-10-07 11:58:58 anthonybaxter Exp $
 ''' Relational database (SQL) backend common code.
 
 Basics:
@@ -145,6 +145,21 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database):
         # commit
         self.conn.commit()
 
+    def refresh_database(self):
+        # now detect changes in the schema
+        for classname, spec in self.classes.items():
+            dbspec = self.database_schema[classname]
+            self.update_class(spec, dbspec, force=1)
+            self.database_schema[classname] = spec.schema()
+        # update the database version of the schema
+        self.sql('delete from schema')
+        self.save_dbschema(self.database_schema)
+        # reindex the db 
+        self.reindex()
+        # commit
+        self.conn.commit()
+
+
     def reindex(self):
         for klass in self.classes.values():
             for nodeid in klass.list():
@@ -170,9 +185,10 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database):
         cols.sort()
         return cols, mls
 
-    def update_class(self, spec, old_spec):
+    def update_class(self, spec, old_spec, force=0):
         ''' Determine the differences between the current spec and the
-            database version of the spec, and update where necessary
+            database version of the spec, and update where necessary.
+            If 'force' is true, update the database anyway.
         '''
         new_spec = spec
         new_has = new_spec.properties.has_key
@@ -180,7 +196,7 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database):
         new_spec = new_spec.schema()
         new_spec[1].sort()
         old_spec[1].sort()
-        if new_spec == old_spec:
+        if not force and new_spec == old_spec:
             # no changes
             return 0
 
@@ -188,16 +204,33 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database):
             print >>hyperdb.DEBUG, 'update_class FIRING'
 
         # key property changed?
-        if old_spec[0] != new_spec[0]:
+        if force or old_spec[0] != new_spec[0]:
             if __debug__:
                 print >>hyperdb.DEBUG, 'update_class setting keyprop', `spec[0]`
             # XXX turn on indexing for the key property. 
+            index_sql = 'drop index _%s_%s_idx'%(
+                        spec.classname, old_spec[0])
+            if __debug__:
+                print >>hyperdb.DEBUG, 'drop_index', (self, index_sql)
+            try:
+                self.cursor.execute(index_sql1)
+            except:
+                # Hackage. Until we update the schema to include some 
+                # backend-specific knowledge, assume that this might fail.
+                pass
+
+            index_sql = 'create index _%s_%s_idx on _%s(%s)'%(
+                        spec.classname, new_spec[0],
+                        spec.classname, new_spec[0])
+            if __debug__:
+                print >>hyperdb.DEBUG, 'create_index', (self, index_sql)
+            self.cursor.execute(index_sql1)
 
         # detect multilinks that have been removed, and drop their table
         old_has = {}
         for name,prop in old_spec[1]:
             old_has[name] = 1
-            if not new_has(name) and isinstance(prop, Multilink):
+            if (force or not new_has(name)) and isinstance(prop, Multilink):
                 # it's a multilink, and it's been removed - drop the old
                 # table. First drop indexes.
                 index_sqls = [ 'drop index %s_%s_l_idx'%(spec.classname, ml),
@@ -224,7 +257,7 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database):
         for propname,x in new_spec[1]:
             prop = properties[propname]
             if isinstance(prop, Multilink):
-                if not old_has(propname):
+                if force or not old_has(propname):
                     # we need to create the new table
                     self.create_multilink_table(spec, propname)
             elif old_has(propname):
index 78ca20e1a47fd97eb11758f9388151ca5cfd3c4a..a524b1937563f7fbb03db15ba5b8adcb391144e5 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: hyperdb.py,v 1.88 2003-09-04 00:47:01 richard Exp $
+# $Id: hyperdb.py,v 1.89 2003-10-07 11:58:57 anthonybaxter Exp $
 
 """
 Hyperdatabase implementation, especially field types.
@@ -188,7 +188,15 @@ concrete backend Class.
         raise NotImplementedError
 
     def post_init(self):
-        """Called once the schema initialisation has finished."""
+        """Called once the schema initialisation has finished. 
+           If 'refresh' is true, we want to rebuild the backend
+           structures.
+        """
+        raise NotImplementedError
+
+    def refresh_database(self):
+        """Called to indicate that the backend should rebuild all tables
+           and structures. Not called in normal usage."""
         raise NotImplementedError
 
     def __getattr__(self, classname):