index 1f1013c285c9302cf373bacea0e6927b38931c13..04100d09316daac2229e5979670148f0cbdc4b30 100644 (file)
-# $Id: back_sqlite.py,v 1.15 2004-03-12 04:08:59 richard Exp $
+# $Id: back_sqlite.py,v 1.16 2004-03-15 05:50:20 richard Exp $
'''Implements a backend for SQLite.
See https://pysqlite.sourceforge.net/ for pysqlite info
's_last_use varchar, s_user varchar)')
self.cursor.execute('create index sessions_key_idx on sessions(s_key)')
+ def add_actor_column(self):
+ # update existing tables to have the new actor column
+ tables = self.database_schema['tables']
+ for classname, spec in self.classes.items():
+ if tables.has_key(classname):
+ dbspec = tables[classname]
+ self.update_class(spec, dbspec, force=1, adding_actor=1)
+
+ def update_class(self, spec, old_spec, force=0, adding_actor=0):
+ ''' Determine the differences between the current spec and the
+ database version of the spec, and update where necessary.
+
+ If 'force' is true, update the database anyway.
+
+ SQLite doesn't have ALTER TABLE, so we have to copy and
+ regenerate the tables with the new schema.
+ '''
+ new_has = spec.properties.has_key
+ new_spec = spec.schema()
+ new_spec[1].sort()
+ old_spec[1].sort()
+ if not force and new_spec == old_spec:
+ # no changes
+ return 0
+
+ if __debug__:
+ print >>hyperdb.DEBUG, 'update_class FIRING'
+
+ # detect multilinks that have been removed, and drop their table
+ old_has = {}
+ for name,prop in old_spec[1]:
+ old_has[name] = 1
+ if new_has(name) or not isinstance(prop, hyperdb.Multilink):
+ continue
+ # it's a multilink, and it's been removed - drop the old
+ # table. First drop indexes.
+ self.drop_multilink_table_indexes(spec.classname, ml)
+ sql = 'drop table %s_%s'%(spec.classname, prop)
+ if __debug__:
+ print >>hyperdb.DEBUG, 'update_class', (self, sql)
+ self.cursor.execute(sql)
+ old_has = old_has.has_key
+
+ # now figure how we populate the new table
+ if adding_actor:
+ fetch = ['_activity', '_creation', '_creator']
+ else:
+ fetch = ['_actor', '_activity', '_creation', '_creator']
+ properties = spec.getprops()
+ for propname,x in new_spec[1]:
+ prop = properties[propname]
+ if isinstance(prop, hyperdb.Multilink):
+ if force or not old_has(propname):
+ # we need to create the new table
+ self.create_multilink_table(spec, propname)
+ elif old_has(propname):
+ # we copy this col over from the old table
+ fetch.append('_'+propname)
+
+ # select the data out of the old table
+ fetch.append('id')
+ fetch.append('__retired__')
+ fetchcols = ','.join(fetch)
+ cn = spec.classname
+ sql = 'select %s from _%s'%(fetchcols, cn)
+ if __debug__:
+ print >>hyperdb.DEBUG, 'update_class', (self, sql)
+ self.cursor.execute(sql)
+ olddata = self.cursor.fetchall()
+
+ # TODO: update all the other index dropping code
+ self.drop_class_table_indexes(cn, old_spec[0])
+
+ # drop the old table
+ self.cursor.execute('drop table _%s'%cn)
+
+ # create the new table
+ self.create_class_table(spec)
+
+ if olddata:
+ # do the insert of the old data - the new columns will have
+ # NULL values
+ args = ','.join([self.arg for x in fetch])
+ sql = 'insert into _%s (%s) values (%s)'%(cn, fetchcols, args)
+ if __debug__:
+ print >>hyperdb.DEBUG, 'update_class', (self, sql, olddata[0])
+ for entry in olddata:
+ self.cursor.execute(sql, tuple(entry))
+
+ return 1
+
def sql_close(self):
''' Squash any error caused by us already having closed the
connection.