Mercurial > p > roundup > code
comparison roundup/backends/rdbms_common.py @ 2417:fe722c32ce0c maint-0.7
merge from HEAD
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Wed, 09 Jun 2004 06:16:56 +0000 |
| parents | 1ccfcfeca61b |
| children | e4f06fcbbc89 |
comparison
equal
deleted
inserted
replaced
| 2408:e12a610eb7f3 | 2417:fe722c32ce0c |
|---|---|
| 1 # $Id: rdbms_common.py,v 1.98.2.5 2004-05-29 02:09:13 richard Exp $ | 1 # $Id: rdbms_common.py,v 1.98.2.6 2004-06-09 06:16:56 richard Exp $ |
| 2 ''' Relational database (SQL) backend common code. | 2 ''' Relational database (SQL) backend common code. |
| 3 | 3 |
| 4 Basics: | 4 Basics: |
| 5 | 5 |
| 6 - map roundup classes to relational tables | 6 - map roundup classes to relational tables |
| 141 if schema: | 141 if schema: |
| 142 self.database_schema = eval(schema[0]) | 142 self.database_schema = eval(schema[0]) |
| 143 else: | 143 else: |
| 144 self.database_schema = {} | 144 self.database_schema = {} |
| 145 | 145 |
| 146 def save_dbschema(self, schema): | 146 def save_dbschema(self): |
| 147 ''' Save the schema definition that the database currently implements | 147 ''' Save the schema definition that the database currently implements |
| 148 ''' | 148 ''' |
| 149 s = repr(self.database_schema) | 149 s = repr(self.database_schema) |
| 150 self.sql('delete from schema') | |
| 150 self.sql('insert into schema values (%s)', (s,)) | 151 self.sql('insert into schema values (%s)', (s,)) |
| 151 | 152 |
| 152 def post_init(self): | 153 def post_init(self): |
| 153 ''' Called once the schema initialisation has finished. | 154 ''' Called once the schema initialisation has finished. |
| 154 | 155 |
| 176 del tables[classname] | 177 del tables[classname] |
| 177 save = 1 | 178 save = 1 |
| 178 | 179 |
| 179 # update the database version of the schema | 180 # update the database version of the schema |
| 180 if save: | 181 if save: |
| 181 self.sql('delete from schema') | 182 self.save_dbschema() |
| 182 self.save_dbschema(self.database_schema) | |
| 183 | 183 |
| 184 # reindex the db if necessary | 184 # reindex the db if necessary |
| 185 if self.indexer.should_reindex(): | 185 if self.indexer.should_reindex(): |
| 186 self.reindex() | 186 self.reindex() |
| 187 | 187 |
| 188 # commit | 188 # commit |
| 189 self.sql_commit() | 189 self.sql_commit() |
| 190 | 190 |
| 191 # update this number when we need to make changes to the SQL structure | 191 # update this number when we need to make changes to the SQL structure |
| 192 # of the backen database | 192 # of the backen database |
| 193 current_db_version = 2 | 193 current_db_version = 3 |
| 194 def upgrade_db(self): | 194 def upgrade_db(self): |
| 195 ''' Update the SQL database to reflect changes in the backend code. | 195 ''' Update the SQL database to reflect changes in the backend code. |
| 196 | 196 |
| 197 Return boolean whether we need to save the schema. | 197 Return boolean whether we need to save the schema. |
| 198 ''' | 198 ''' |
| 211 | 211 |
| 212 # version 1 doesn't have the OTK, session and indexing in the | 212 # version 1 doesn't have the OTK, session and indexing in the |
| 213 # database | 213 # database |
| 214 self.create_version_2_tables() | 214 self.create_version_2_tables() |
| 215 | 215 |
| 216 if version == 2: | |
| 217 self.fix_version_2_tables() | |
| 218 | |
| 216 self.database_schema['version'] = self.current_db_version | 219 self.database_schema['version'] = self.current_db_version |
| 217 return 1 | 220 return 1 |
| 218 | 221 |
| 222 def fix_version_2_tables(self): | |
| 223 '''Default (used by sqlite): NOOP''' | |
| 224 pass | |
| 225 | |
| 226 def _convert_journal_tables(self): | |
| 227 '''Get current journal table contents, drop the table and re-create''' | |
| 228 c = self.cursor | |
| 229 cols = ','.join('nodeid date tag action params'.split()) | |
| 230 for klass in self.classes.values(): | |
| 231 # slurp and drop | |
| 232 sql = 'select %s from %s__journal order by date'%(cols, | |
| 233 klass.classname) | |
| 234 c.execute(sql) | |
| 235 contents = c.fetchall() | |
| 236 self.drop_journal_table_indexes(klass.classname) | |
| 237 c.execute('drop table %s__journal'%klass.classname) | |
| 238 | |
| 239 # re-create and re-populate | |
| 240 self.create_journal_table(klass) | |
| 241 a = self.arg | |
| 242 sql = 'insert into %s__journal (%s) values (%s,%s,%s,%s,%s)'%( | |
| 243 klass.classname, cols, a, a, a, a, a) | |
| 244 for row in contents: | |
| 245 # no data conversion needed | |
| 246 self.cursor.execute(sql, row) | |
| 247 | |
| 248 def _convert_string_properties(self): | |
| 249 '''Get current Class tables that contain String properties, and | |
| 250 convert the VARCHAR columns to TEXT''' | |
| 251 c = self.cursor | |
| 252 for klass in self.classes.values(): | |
| 253 # slurp and drop | |
| 254 cols, mls = self.determine_columns(klass.properties.items()) | |
| 255 scols = ','.join([i[0] for i in cols]) | |
| 256 sql = 'select id,%s from _%s'%(scols, klass.classname) | |
| 257 c.execute(sql) | |
| 258 contents = c.fetchall() | |
| 259 self.drop_class_table_indexes(klass.classname, klass.getkey()) | |
| 260 c.execute('drop table _%s'%klass.classname) | |
| 261 | |
| 262 # re-create and re-populate | |
| 263 self.create_class_table(klass, create_sequence=False) | |
| 264 a = ','.join([self.arg for i in range(len(cols)+1)]) | |
| 265 sql = 'insert into _%s (id,%s) values (%s)'%(klass.classname, | |
| 266 scols, a) | |
| 267 for row in contents: | |
| 268 l = [] | |
| 269 for entry in row: | |
| 270 # mysql will already be a string - psql needs "help" | |
| 271 if entry is not None and not isinstance(entry, type('')): | |
| 272 entry = str(entry) | |
| 273 l.append(entry) | |
| 274 self.cursor.execute(sql, l) | |
| 219 | 275 |
| 220 def refresh_database(self): | 276 def refresh_database(self): |
| 221 self.post_init() | 277 self.post_init() |
| 222 | 278 |
| 223 def reindex(self): | 279 def reindex(self): |
| 225 for nodeid in klass.list(): | 281 for nodeid in klass.list(): |
| 226 klass.index(nodeid) | 282 klass.index(nodeid) |
| 227 self.indexer.save_index() | 283 self.indexer.save_index() |
| 228 | 284 |
| 229 hyperdb_to_sql_datatypes = { | 285 hyperdb_to_sql_datatypes = { |
| 230 hyperdb.String : 'VARCHAR(255)', | 286 hyperdb.String : 'TEXT', |
| 231 hyperdb.Date : 'TIMESTAMP', | 287 hyperdb.Date : 'TIMESTAMP', |
| 232 hyperdb.Link : 'INTEGER', | 288 hyperdb.Link : 'INTEGER', |
| 233 hyperdb.Interval : 'VARCHAR(255)', | 289 hyperdb.Interval : 'VARCHAR(255)', |
| 234 hyperdb.Password : 'VARCHAR(255)', | 290 hyperdb.Password : 'VARCHAR(255)', |
| 235 hyperdb.Boolean : 'BOOLEAN', | 291 hyperdb.Boolean : 'BOOLEAN', |
| 464 def create_multilink_table(self, spec, ml): | 520 def create_multilink_table(self, spec, ml): |
| 465 ''' Create a multilink table for the "ml" property of the class | 521 ''' Create a multilink table for the "ml" property of the class |
| 466 given by the spec | 522 given by the spec |
| 467 ''' | 523 ''' |
| 468 # create the table | 524 # create the table |
| 469 sql = 'create table %s_%s (linkid varchar, nodeid varchar)'%( | 525 sql = 'create table %s_%s (linkid varchar(255), nodeid varchar(255))'%( |
| 470 spec.classname, ml) | 526 spec.classname, ml) |
| 471 if __debug__: | 527 if __debug__: |
| 472 print >>hyperdb.DEBUG, 'create_class', (self, sql) | 528 print >>hyperdb.DEBUG, 'create_class', (self, sql) |
| 473 self.cursor.execute(sql) | 529 self.cursor.execute(sql) |
| 474 self.create_multilink_table_indexes(spec, ml) | 530 self.create_multilink_table_indexes(spec, ml) |
| 1090 return self.cursor.fetchall() | 1146 return self.cursor.fetchall() |
| 1091 | 1147 |
| 1092 def pack(self, pack_before): | 1148 def pack(self, pack_before): |
| 1093 ''' Delete all journal entries except "create" before 'pack_before'. | 1149 ''' Delete all journal entries except "create" before 'pack_before'. |
| 1094 ''' | 1150 ''' |
| 1095 # get a 'yyyymmddhhmmss' version of the date | 1151 date_stamp = self.hyperdb_to_sql_value[Date](pack_before) |
| 1096 date_stamp = pack_before.serialise() | |
| 1097 | 1152 |
| 1098 # do the delete | 1153 # do the delete |
| 1099 for classname in self.classes.keys(): | 1154 for classname in self.classes.keys(): |
| 1100 sql = "delete from %s__journal where date<%s and "\ | 1155 sql = "delete from %s__journal where date<%s and "\ |
| 1101 "action<>'create'"%(classname, self.arg) | 1156 "action<>'create'"%(classname, self.arg) |
