comparison roundup/backends/back_sqlite.py @ 2077:3e0961d6d44d

Added the "actor" property. Metakit backend not done (still not confident I know how it's supposed to work ;) Currently it will come up as NULL in the RDBMS backends for older items. The *dbm backends will look up the journal. I hope to remedy the former before 0.7's release. Fixed a bunch of migration issues in the rdbms backends while I was at it (index changes for key prop changes) and simplified the class table update code for RDBMSes that have "alter table" in their command set (ie. not sqlite) ... migration from "version 1" to "version 2" still hasn't actually been tested yet though.
author Richard Jones <richard@users.sourceforge.net>
date Mon, 15 Mar 2004 05:50:20 +0000
parents b1704ba7be41
children c091cacdc505
comparison
equal deleted inserted replaced
2076:2a4309450202 2077:3e0961d6d44d
1 # $Id: back_sqlite.py,v 1.15 2004-03-12 04:08:59 richard Exp $ 1 # $Id: back_sqlite.py,v 1.16 2004-03-15 05:50:20 richard Exp $
2 '''Implements a backend for SQLite. 2 '''Implements a backend for SQLite.
3 3
4 See https://pysqlite.sourceforge.net/ for pysqlite info 4 See https://pysqlite.sourceforge.net/ for pysqlite info
5 ''' 5 '''
6 __docformat__ = 'restructuredtext' 6 __docformat__ = 'restructuredtext'
46 self.cursor.execute('create index otks_key_idx on otks(otk_key)') 46 self.cursor.execute('create index otks_key_idx on otks(otk_key)')
47 self.cursor.execute('create table sessions (s_key varchar, ' 47 self.cursor.execute('create table sessions (s_key varchar, '
48 's_last_use varchar, s_user varchar)') 48 's_last_use varchar, s_user varchar)')
49 self.cursor.execute('create index sessions_key_idx on sessions(s_key)') 49 self.cursor.execute('create index sessions_key_idx on sessions(s_key)')
50 50
51 def add_actor_column(self):
52 # update existing tables to have the new actor column
53 tables = self.database_schema['tables']
54 for classname, spec in self.classes.items():
55 if tables.has_key(classname):
56 dbspec = tables[classname]
57 self.update_class(spec, dbspec, force=1, adding_actor=1)
58
59 def update_class(self, spec, old_spec, force=0, adding_actor=0):
60 ''' Determine the differences between the current spec and the
61 database version of the spec, and update where necessary.
62
63 If 'force' is true, update the database anyway.
64
65 SQLite doesn't have ALTER TABLE, so we have to copy and
66 regenerate the tables with the new schema.
67 '''
68 new_has = spec.properties.has_key
69 new_spec = spec.schema()
70 new_spec[1].sort()
71 old_spec[1].sort()
72 if not force and new_spec == old_spec:
73 # no changes
74 return 0
75
76 if __debug__:
77 print >>hyperdb.DEBUG, 'update_class FIRING'
78
79 # detect multilinks that have been removed, and drop their table
80 old_has = {}
81 for name,prop in old_spec[1]:
82 old_has[name] = 1
83 if new_has(name) or not isinstance(prop, hyperdb.Multilink):
84 continue
85 # it's a multilink, and it's been removed - drop the old
86 # table. First drop indexes.
87 self.drop_multilink_table_indexes(spec.classname, ml)
88 sql = 'drop table %s_%s'%(spec.classname, prop)
89 if __debug__:
90 print >>hyperdb.DEBUG, 'update_class', (self, sql)
91 self.cursor.execute(sql)
92 old_has = old_has.has_key
93
94 # now figure how we populate the new table
95 if adding_actor:
96 fetch = ['_activity', '_creation', '_creator']
97 else:
98 fetch = ['_actor', '_activity', '_creation', '_creator']
99 properties = spec.getprops()
100 for propname,x in new_spec[1]:
101 prop = properties[propname]
102 if isinstance(prop, hyperdb.Multilink):
103 if force or not old_has(propname):
104 # we need to create the new table
105 self.create_multilink_table(spec, propname)
106 elif old_has(propname):
107 # we copy this col over from the old table
108 fetch.append('_'+propname)
109
110 # select the data out of the old table
111 fetch.append('id')
112 fetch.append('__retired__')
113 fetchcols = ','.join(fetch)
114 cn = spec.classname
115 sql = 'select %s from _%s'%(fetchcols, cn)
116 if __debug__:
117 print >>hyperdb.DEBUG, 'update_class', (self, sql)
118 self.cursor.execute(sql)
119 olddata = self.cursor.fetchall()
120
121 # TODO: update all the other index dropping code
122 self.drop_class_table_indexes(cn, old_spec[0])
123
124 # drop the old table
125 self.cursor.execute('drop table _%s'%cn)
126
127 # create the new table
128 self.create_class_table(spec)
129
130 if olddata:
131 # do the insert of the old data - the new columns will have
132 # NULL values
133 args = ','.join([self.arg for x in fetch])
134 sql = 'insert into _%s (%s) values (%s)'%(cn, fetchcols, args)
135 if __debug__:
136 print >>hyperdb.DEBUG, 'update_class', (self, sql, olddata[0])
137 for entry in olddata:
138 self.cursor.execute(sql, tuple(entry))
139
140 return 1
141
51 def sql_close(self): 142 def sql_close(self):
52 ''' Squash any error caused by us already having closed the 143 ''' Squash any error caused by us already having closed the
53 connection. 144 connection.
54 ''' 145 '''
55 try: 146 try:

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