From: anthonybaxter Date: Tue, 7 Oct 2003 11:58:58 +0000 (+0000) Subject: hyperdb grows a refresh_database() method. There will be a future X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=04c54950f7116e1487d682dd2e2ab73f59fa4171;p=roundup.git 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. :-( git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1907 57a73879-2fb5-44c3-a270-3262357dd7e2 --- diff --git a/roundup/backends/back_anydbm.py b/roundup/backends/back_anydbm.py index 8d7ecd8..8dae659 100644 --- a/roundup/backends/back_anydbm.py +++ b/roundup/backends/back_anydbm.py @@ -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(): diff --git a/roundup/backends/back_metakit.py b/roundup/backends/back_metakit.py index 68dc295..737d08d 100755 --- a/roundup/backends/back_metakit.py +++ b/roundup/backends/back_metakit.py @@ -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(): diff --git a/roundup/backends/rdbms_common.py b/roundup/backends/rdbms_common.py index b88b2e2..0092101 100644 --- a/roundup/backends/rdbms_common.py +++ b/roundup/backends/rdbms_common.py @@ -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): diff --git a/roundup/hyperdb.py b/roundup/hyperdb.py index 78ca20e..a524b19 100644 --- a/roundup/hyperdb.py +++ b/roundup/hyperdb.py @@ -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):