changeset 1840:91a4619b1a14

hyperdb grows a refresh_database() method. There will be a future roundup-admin command to invoke this. XXXX Unit tests do _not_ cover large slabs of the hyperdb backend code, it seems. :-(
author Anthony Baxter <anthonybaxter@users.sourceforge.net>
date Tue, 07 Oct 2003 11:58:58 +0000
parents 06f5b36b201b
children 24fb163ddece
files roundup/backends/back_anydbm.py roundup/backends/back_metakit.py roundup/backends/rdbms_common.py roundup/hyperdb.py
diffstat 4 files changed, 60 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/roundup/backends/back_anydbm.py	Tue Oct 07 08:52:12 2003 +0000
+++ b/roundup/backends/back_anydbm.py	Tue Oct 07 11:58:58 2003 +0000
@@ -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 @@
         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():
--- a/roundup/backends/back_metakit.py	Tue Oct 07 08:52:12 2003 +0000
+++ b/roundup/backends/back_metakit.py	Tue Oct 07 11:58:58 2003 +0000
@@ -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 @@
         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():
--- a/roundup/backends/rdbms_common.py	Tue Oct 07 08:52:12 2003 +0000
+++ b/roundup/backends/rdbms_common.py	Tue Oct 07 11:58:58 2003 +0000
@@ -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 @@
         # 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 @@
         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 @@
         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 @@
             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 @@
         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):
--- a/roundup/hyperdb.py	Tue Oct 07 08:52:12 2003 +0000
+++ b/roundup/hyperdb.py	Tue Oct 07 11:58:58 2003 +0000
@@ -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 @@
         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):

Roundup Issue Tracker: http://roundup-tracker.org/